矢量用vec创建的矢量!宏包含不同的容量

Dom*_* M. 10 vector rust

我有一个向量matrix_a,其中包含3个向量,并使用vec!宏进行初始化.

由于每个向量的容量应为3,Vec::with_capacity(dim)但只有最后一个向量的容量为3.其他向量的容量为0.

有人可以解释为什么会这样吗?

fn main() {
    let dim = 3;
    let matrix_a: Vec<Vec<i32>> = vec![Vec::with_capacity(dim); dim];

    for vector in matrix_a{
        println!("Capacity of vector: {}", vector.capacity());
    }
}
Run Code Online (Sandbox Code Playgroud)

输出:

Capacity of vector: 0
Capacity of vector: 0
Capacity of vector: 3
Run Code Online (Sandbox Code Playgroud)

Mat*_* M. 12

根据文档,vec!定义为:

macro_rules! vec {
    ( $ elem : expr ; $ n : expr ) => (
        $ crate:: vec:: from_elem ( $ elem , $ n )
    );
    ( $ ( $ x : expr ) , * ) => (
        < [ _ ] > :: into_vec (
            $ crate:: boxed:: Box:: new ( [ $ ( $ x ) , * ] )
        )
    );
    ( $ ( $ x : expr , ) * ) => ( vec ! [ $ ( $ x ) , * ] )
}
Run Code Online (Sandbox Code Playgroud)

在您的情况下,它意味着:

vec![Vec::with_capacity(dim); dim]
Run Code Online (Sandbox Code Playgroud)

扩展为:

std::vec::from_elem(Vec::with_capacity(dim), dim)
Run Code Online (Sandbox Code Playgroud)

Vec::from_elem隐藏在文档中的定义,但可以在源代码中找到:

pub fn from_elem<T: Clone>(elem: T, n: usize) -> Vec<T> {
    unsafe {
        let mut v = Vec::with_capacity(n);
        let mut ptr = v.as_mut_ptr();

        // Write all elements except the last one
        for i in 1..n {
            ptr::write(ptr, Clone::clone(&elem));
            ptr = ptr.offset(1);
            v.set_len(i); // Increment the length in every step in case Clone::clone() panics
        }

        if n > 0 {
            // We can write the last element directly without cloning needlessly
            ptr::write(ptr, elem);
            v.set_len(n);
        }

        v
    }
}
Run Code Online (Sandbox Code Playgroud)

这就是解开神秘之心的地方:

  • n - 1对于n - 1向量的第一个元素,元素被克隆次数,然后移动到第n n个插槽中.
  • 克隆载体不会克隆其容量,只能克隆其元素.

因此,如果不是预期的结果,您获得的结果与预期完全一致.


Vee*_*rac 8

如上所述,这是因为vec![x; y]克隆了价值.为避免这种情况,您可以改为使用collect矢量:

let matrix_a: Vec<Vec<i32>> = (0..dim).map(|_| Vec::with_capacity(dim)).collect();
Run Code Online (Sandbox Code Playgroud)

这会单独初始化每个元素,为您提供完整的分配.