创建一个大小为 n 的空向量,不填充任何东西

Create an empty vector of size n, and not fill it with anything

我需要初始化一个向量以用作缓冲区。在我把东西放进去之前我不关心它包含什么值,所以我不希望程序浪费时间用零填充它。我知道 with_capacity,但它需要我 push() 个元素,这很不方便,因为我需要不断检查我之前是否将某些内容推送到索引。

基本上,我正在寻找这个 C++ 数组的等价物:

int* arr = new int[size];
arr[2]; // random garbage

如果您的目标是存储整数值,您可以有效地使用 vec 宏来初始化向量:

let vec = vec![0; 5];
assert_eq!(vec, [0, 0, 0, 0, 0]);

这种形式的宏调用有两个参数。第一个是要插入的元素的值。第二个是要插入的元素的副本数。

相当于:

let mut vec = Vec::with_capacity(5);
vec.resize(5, 0);

有关详细信息,请参阅 https://doc.rust-lang.org/std/vec/struct.Vec.html

请注意,当您说:

waste time filling it with zeroes

您可能想对此进行量化。请注意,我上面描述的操作在一般情况下似乎是 O(n)(参见 https://doc.rust-lang.org/src/alloc/vec/mod.rs.html#2315),因此它可能不适合您的用例。

但是,如果您的向量包含整数值,则根据 的解释,操作很可能为 O(1)。如其他地方所说,请先进行基准测试。

如果出于性能原因无法填充向量(但请进行基准测试!),则需要使用不安全代码。你可以例如使用 Vec::spare_capacity_mut() (or the nightly Vec::split_at_spare_mut()) to access the elements, then Vec::set_len()。例如:

let mut v = Vec::with_capacity(N);
for (i, item) in v.spare_capacity_mut().iter_mut().enumerate() {
    item.write(i);
}
// SAFETY: All elements were initialized.
unsafe {
    v.set_len(N);
}

Playground.

或者您可以使用 as_mut_ptr() 手动管理指针(不太推荐,但如果某些元素已经初始化可能会更好:

let mut v = Vec::<i32>::with_capacity(N);
// SFAETY: There are enough elements (even if uninitialized).
let all_elements = unsafe {
    std::slice::from_raw_parts_mut(v.as_mut_ptr().cast::<std::mem::MaybeUninit<_>>(), N)
};
for (i, item) in all_elements.iter_mut().enumerate() {
    item.write(i);
}
// SAFETY: All elements were initialized.
unsafe {
    v.set_len(N);
}

Playground.

这很难,在某种程度上,anti-idiomatic,因为 Rust 会尝试以任何方式阻止您操作未初始化的内存。而且,尽管如果你来自 C++,这听起来像是一个限制,但你必须意识到,并不是所有的东西都从字面上从 C++ 翻译成 Rust,即使这两种语言有很多相似之处。

例如,如果您:

  • 不想用默认值填充向量,
  • 在继续时不想要 push 个值,

那么你最好构建一个可迭代对象,然后 collecting 它。

您也可以用 Nones 填充向量。

特别是,Rust 鼓励您不要让变量指向未初始化的内存。也就是说,即使您实现(正如我稍后将解释的那样)拥有未初始化的内存,Rust 也会要求您在访问它时使用 unsafe 块,直到您“证明”它已全部初始化,即使这样您从不 允许从未初始化的内存中读取,这会导致 UB(这是最糟糕的情况)。

如果您真的想使用未初始化的内存,请阅读 relevant chapter of the rustnomicon. In the end, what you will use is MaybeUninit。但是,也请仔细阅读 rustnomicon(不仅是 MaybeUninit 的文档页面),因为它包含微妙之处。