如何在Rust中为Vec<T>分配空间?

20

我想创建一个 Vec<T> 并为它腾出一些空间,但我不知道该如何做,令我惊讶的是,在官方文档中几乎没有关于这个基本类型的介绍。

let mut v: Vec<i32> = Vec<i32>(SIZE); // How do I do this ?

for i in 0..SIZE {
    v[i] = i;
}

我知道我可以创建一个空的Vec<T>并用push填充它,但是我不想这样做,因为写入索引i处的值时,我不总是知道是否已经插入了一个值。出于明显的性能原因,我不想编写以下内容:

if i >= len(v) {
    v.push(x);
} else {
    v[i] = x;
}

当然,我也不能使用vec!语法。


如果您正在创建一个新的向量,那么您将会知道该值是否存在。请注意,这里有很多答案都假设您正在创建一个新的向量,如果不是这种情况(从问题的第二部分似乎并非如此),那么在问题中更清楚地表明这一点会更好。对于新向量和现有向量的答案是非常不同的。 - ideasman42
3个回答

55

虽然接受回答中的vec![elem; count]足以创建一个所有元素都等于同一值的向量,但还有其他方便的函数。

Vec::with_capacity()可以创建具有给定容量但长度为零的向量。这意味着在达到此容量之前,push()调用不会重新分配向量,使得push()本质上是免费的:

fn main() {
    let mut v = Vec::with_capacity(10);
    for i in 0..10 {
        v.push(i);
    }
    println!("{:?}", v);
}

你也可以轻松地从迭代器中 collect() 一个向量。例如:

fn main() {
    let v: Vec<_> = (1..10).collect();
    println!("{:?}", v);
}

最后,有时您的向量包含基本类型的值,并且应该被用作缓冲区(例如在网络通信中)。在这种情况下,您可以使用 Vec::with_capacity() + set_len() 的不安全方法:

fn main() {
    let mut v = Vec::with_capacity(10);
    unsafe { v.set_len(10); }
    for i in 0..10 {
        v[i] = i;
    }
    println!("{:?}", v);
}

注意,如果您的向量包含具有析构函数或引用的值,则必须特别小心-很容易使析构函数在未初始化的内存块上运行或以这种方式获得无效引用。如果您只使用向量的初始化部分,则它也会正常工作(现在您必须自己进行跟踪)。要了解有关未初始化内存的所有可能危险,请阅读mem::uninitialized()文档。


set_len可以正确处理非Copy类型:您只需要小心即可。但是,对于Copy类型,例如&intCopy,但随机未初始化的内存很可能不是有效的&int。(这非常危险!) - huon
@dbaupp,是的,我可能没有表达清楚。谢谢! - Vladimir Matveev
最好使用枚举迭代向量,这样每个赋值就不需要进行边界检查。(可能边界检查会被优化掉 - 但这取决于循环的复杂性) - ideasman42

18
你可以使用vec!宏的第一种语法,具体为vec![elem; count]。例如:
vec![1; 10]

将创建一个包含10个1Vec<_>(类型_稍后将确定或默认为i32)。传递给宏的elem必须实现Clonecount也可以是一个变量。


谢谢。好吧,这在文档中有提到。虽然我搜索时找不到它。 - Fabien
2
这个不再起作用了,那个方法似乎已经被移除了。 - Amandasaurus
1
@Rory 现在使用 1.0 版本运行。 - Lukas Kalbertodt
这比 ::with_capacity() 更容易记住。在最新的 Rust 1.4.4 中,vec![0; 10] 可以正常工作。 - Charlie 木匠

3
这是一个名为Vec::resize的方法:
fn resize(&mut self, new_len: usize, value: T)

这段代码将一个空向量调整为1024个元素,并用值7填充:
let mut vec: Vec<i32> = Vec::new();
vec.resize(1024, 7);

1
值得注意的是,这仅在您分配相同值时才有效 - OP 分配递增索引。 - ideasman42

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接