fn main() {
let vec0 = vec![0; 10];
let mut vec1 = vec![];
for _ in 0..10 {
vec1.push(0);
}
assert_eq!(vec0.len(), vec1.len());
}
字符串
在本例中,vec0
和vec1
在使用index访问其项时是相同的。但是这两种初始化的方法会导致不同的内存布局吗?
更多背景:我正在构建一个(希望如此)缓存友好的容器(到目前为止是Vec<T>
)来利用缓存局部性。通常在C++中,你可以分配一个具有动态长度(auto array = new DataType[length];
)的新数组来强制紧凑的内存布局,但在Rust中,变量长度数组是不可能的。因此,我正在寻找一种构建Vec<T>
的方法,它可以提高执行期间的缓存命中/未命中率。
2条答案
按热度按时间r6l8ljro1#
正如@AleksanderKrauze所回答的那样,两者之间的唯一区别是最终容量和初始化时间,这是由于
for
循环中可能存在多次重新分配。但是,你可以在Rust中做一个与C++动态数组等效的操作:字符串
Playground
kcwpcxri2#
从documentation
具有堆分配内容的连续可增长数组类型,写为
Vec<T>
Rust中的
std::vec::Vec<T>
与C中的std::vector<T>
几乎相同。它们都将数据存储在一个连续的元素数组中。在Rust中,这一点更加明显,因为Vec<T>
实现了Deref<Target = [T]>
。而所有的slices表示“进入连续序列的视图”。在创建
Vec
的不同方法之间,数据在内存中的布局方式没有区别。唯一的区别可能是容量的大小,因为宏vec!
将使用它的with_capacity方法创建向量,而当你推到一个向量时,你将不得不重新分配,由于摊销,你最终可能会得到不同的容量(使用宏也会更快,因为你不必做所有这些重新分配)。通常在C中,你可以分配一个具有动态长度(
auto array = new DataType[length];
)的新数组来强制紧凑的内存布局,但在Rust中,可变长度数组是根本不可能的。这并不完全正确。在 * 标准库 * 中没有 stable 和 safe 方法来做这件事。但是,如果你想自己使用分配器,或者使用一些不稳定的特性(例如Box::new_uninit_slice),你可以创建完全相同的堆存储数组。虽然
Vec
可能会工作得很好。请记住使用with_capacity
创建它。