从文档中可以看出:
pub fn new(x: T) -> Box 在堆上分配内存,然后将 x 放入其中。
但“地点”是一个棘手的词。如果我们写
let arr_boxed = Box::new([0;1000]);
会[0;1000]
在堆上就地初始化吗?
如果我们写
let arr = [0;1000];
let arr_boxed = Box::new(arr);
[0;1000]
编译器是否足够聪明,可以首先在堆上初始化?
从文档中可以看出:
pub fn new(x: T) -> Box 在堆上分配内存,然后将 x 放入其中。
但“地点”是一个棘手的词。如果我们写
let arr_boxed = Box::new([0;1000]);
会[0;1000]
在堆上就地初始化吗?
如果我们写
let arr = [0;1000];
let arr_boxed = Box::new(arr);
[0;1000]
编译器是否足够聪明,可以首先在堆上初始化?
有时。Rust 语言不保证这种优化的发生,并且似乎将其留给 LLVM 来解决。因此,如果先初始化数组然后传递它根本没有关系,因为这对于后端来说本质上是相同的。
在实践中,性能将取决于具体情况。您给出的示例实际上很特殊,因为数据全为零:
在我的测试中,编译器能够将其转换为分配+对
memset
堆数据的调用。注意:仅在打开优化的情况下。在调试模式下它将复制。
另一方面,您可能希望使用已知值初始化数据:
令我恐惧的是,编译器决定初始化堆栈上的整个数据,然后调用
memcpy
. (至少它展开了填充循环):)。即使对于像这样的非常大的数据也会发生这种情况[v; 100000]
,这会因堆栈溢出而使您的程序崩溃。使用编译时已知(非零)文字的[64; 100000]
行为方式相同。如果你真的想确定,你可以这样做:
这是正确的做法。
一个安全版本
baz
是:编译器对其进行了很好的优化,基本上与
baz
.甚至更短
vec![v; 1000].into_boxed_slice().try_into::<Box<[i32; 1000]>>().unwrap()
这可能是最好的版本。