2015-08-25 23 views
9

Mam wektor matrix_a, który zawiera 3 wektory i jest inicjowany za pomocą makra vec!.Wektor wektorów utworzonych za pomocą vec! makro zawiera różne pojemności

Każdy wektor powinien mieć pojemność 3, ze względu na Vec::with_capacity(dim), ale tylko ostatni wektor ma pojemność 3. inne wektory mają pojemność 0.

Może ktoś wyjaśnić, dlaczego tak jest?

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()); 
    } 
} 

wyjściowa:

Capacity of vector: 0 
Capacity of vector: 0 
Capacity of vector: 3 
+2

Dobra, to zabawna ... –

Odpowiedz

11

Według documentation, vec! jest zdefiniowany jako:

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) , * ]) 
} 

w Twoim przypadku, to znaczy, że:

vec![Vec::with_capacity(dim); dim] 

rozpręża do:

std::vec::from_elem(Vec::with_capacity(dim), dim) 

Definicja Vec::from_elem ukryta jest w dokumentacji, ale może być found in the source:

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 
    } 
} 

a to gdzie serce tajemnicy jest rozwiązany:

  • elementu jest sklonowany n - 1 razy, dla n - 1 pierwszych elementów wektora, a następnie przeniesiony do szczeliny n.
  • klonowanie wektora nie klonuje jego pojemności, tylko jego elementy.

W ten sposób otrzymany wynik jest dokładnie taki, jak zamierzono, jeśli nie zgodnie z oczekiwaniami.

6

Jak podano, jest tak, ponieważ vec![x; y] klonuje wartość. Aby tego uniknąć, można zamiast collect Twój wektor:

let matrix_a: Vec<Vec<i32>> = (0..dim).map(|_| Vec::with_capacity(dim)).collect(); 

ten inicjuje każdy element osobno, co daje pełne uprawnienia.

Powiązane problemy