2015-08-25 3 views
9

Ho un vettore matrix_a, che contiene 3 vettori ed è inizializzato con la macro vec!.Vettore di Vettori creato con il vec! macro contiene diverse capacità

ogni vettore dovrebbe avere una capacità di 3, a causa di Vec::with_capacity(dim), ma solo l'ultimo vettore ha una capacità di 3. Gli altri vettori hanno una capacità pari a 0.

Qualcuno può spiegare perché?

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

uscita:

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

OK, è divertente ... –

risposta

11

Secondo il documentation, vec! è definito come:

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

Nel tuo caso, vuol dire che:

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

si espande in:

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

La definizione di Vec::from_elem è nascosto nella documentazione, ma può essere 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 
    } 
} 

E questo dove il cuore del mistero è risolto:

  • l'elemento è clonato n - 1 volte, per i primi elementi del vettore n - 1 e quindi spostato nello slot nth.
  • clonazione di un vettore non clona la sua capacità, solo i suoi elementi.

Quindi il risultato ottenuto è esattamente come previsto, se non come previsto.

6

Come indicato, questo è perché vec![x; y] clona il valore. Per evitare questo, si può invece collect vostro vettore:

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

Questo inizializza separatamente ogni elemento, dando allocazioni completi.

Problemi correlati