How to allocate space for a Vec in Rust?

2019-06-18 05:17发布

问题:

I want to create a Vec<T> and make some room for it, but I don't know how to do it, and, to my surprise, there is almost nothing in the official documentation about this basic type.

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

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

I know I can create an empty Vec<T> and fill it with pushes, but I don't want to do that since I don't always know, when writing a value at index i, if a value was already inserted there yet. I don't want to write, for obvious performance reasons, something like :

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

And, of course, I can't use the vec! syntax either.

回答1:

You can use the first syntax of the vec! macro, specifically vec![elem; count]. For example:

vec![1; 10]

will create a Vec<_> containing 10 1s (the type _ will be determined later or default to i32). The elem given to the macro must implement Clone. The count can be a variable, too.



回答2:

While vec![elem; count] from the accepted answer is sufficient to create a vector with all elements equal to the same value, there are other convenience functions.

Vec::with_capacity() creates a vector with the given capacity but with zero length. It means that until this capacity is reached, push() calls won't reallocate the vector, making push() essentially free:

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

You can also easily collect() a vector from an iterator. Example:

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

And finally, sometimes your vector contains values of primitive type and is supposed to be used as a buffer (e.g. in network communication). In this case you can use Vec::with_capacity() + set_len() unsafe method:

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

Note that you have to be extra careful if your vector contains values with destructors or references - it's easy to get a destructor run over a uninitialized piece of memory or to get an invalid reference this way. It will also work right if you only use initialized part of the vector (you have to track it yourself now). To read about all the possible dangers of uninitialized memory, you can read the documentation of mem::uninitialized().



回答3:

There is the Vec::resize method:

fn resize(&mut self, new_len: usize, value: T)

This code resizes an empty vector to 1024 elements by filling with the value 7:

let mut vec: Vec<i32> = Vec::new();
vec.resize(1024, 7);


标签: vector rust