Do documento diz:
pub fn new(x: T) -> Box Aloca memória no heap e depois coloca x nele.
Mas “lugar” é uma palavra complicada. Se escrevermos
let arr_boxed = Box::new([0;1000]);
Será [0;1000]
inicializado no heap no local?
Se escrevermos
let arr = [0;1000];
let arr_boxed = Box::new(arr);
O compilador será inteligente o suficiente para inicializar o [0;1000]
heap em primeiro lugar?
Às vezes. A linguagem Rust não garante que essa otimização aconteça e parece deixar que o LLVM descubra isso. Por causa disso, não importa se você inicializa o array primeiro e depois o passa, pois isso é essencialmente a mesma coisa para o back-end.
Na prática, o desempenho dependerá do caso. O exemplo que você deu é realmente especial, porque os dados são todos zeros:
Nos meus testes , o compilador conseguiu transformar isso em uma alocação + uma chamada para
memset
os dados do heap.Nota : apenas com as otimizações ativadas. No modo de depuração, ele será copiado.
Por outro lado, você pode querer inicializar seus dados com um valor conhecido:
Para meu horror , o compilador decide inicializar todos os dados na pilha e depois chamar
memcpy
. (Pelo menos desenrolou o loop de preenchimento) :). Isso acontece mesmo para dados realmente grandes, como[v; 100000]
, que travarão seu programa com um estouro de pilha. Usar um literal conhecido em tempo de compilação (diferente de zero)[64; 100000]
se comporta da mesma maneira.Se você realmente quiser ter certeza, você pode fazer algo assim:
que faz a coisa certa .
Uma versão segura
baz
seria:Que o compilador otimiza muito bem , para essencialmente a mesma montagem que o
baz
.Ainda mais curto seria
vec![v; 1000].into_boxed_slice().try_into::<Box<[i32; 1000]>>().unwrap()
qual é provavelmente a melhor versão.