Wann erstellt `vec!` Verschiedene Elemente oder nicht?
Ich bin gerade auf den folgenden Code in Rust gestoßen:
use std::collections::HashMap;
use std::sync::{Arc, Mutex};
fn main() {
let mut v1 = vec![HashMap::<i32, i32>::new(); 2];
v1[0].insert(0,0);
v1[1].insert(1,1);
println!("{:?}", v1);
let v2 = vec![Arc::new(Mutex::new(HashMap::<i32, i32>::new())); 2];
v2[0].lock().unwrap().insert(0,0);
v2[1].lock().unwrap().insert(1,1);
println!("{:?}", v2);
}
// outputs:
// [{0: 0}, {1: 1}]
// [Mutex { data: {0: 0, 1: 1} }, Mutex { data: {0: 0, 1: 1} }]
Link zum Rostspielplatz
Es hat anscheinend v12 verschiedene HashMaps, während v2es nur eine hat. Wie ist das passiert? Sollte nicht zweimal v2ausgewertet Arc::new(Mutex::new(HashMap::<i32, i32>::new()))werden (wie v1tun) und somit zwei verschiedene Elemente erstellen? Ist es irgendwo eine Art "fauler" Bewertung?
Verzeihen Sie meine Rostneulingsfrage, danke im Voraus!
Antworten
Die vec![value; n]Syntax wird verwendet Clone, um den Wert zu duplizieren und den Vektor zu füllen. Die Dokumente erwähnen sogar diese Art von Szenario:
Dies wird verwendet
clone, um einen Ausdruck zu duplizieren. Daher sollte man bei Typen mit einer nicht standardmäßigenCloneImplementierung vorsichtig sein .vec![Rc::new(1); 5]Erstellen Sie beispielsweise einen Vektor mit fünf Verweisen auf denselben Wert für Ganzzahlen mit Boxen, nicht mit fünf Referenzen, die auf Ganzzahlen mit unabhängigen Boxen verweisen.
Der vec!Makroklonwert des bereitgestellten Ausdrucks, um den Vektor bis zur angeforderten Länge zu füllen.
An Arcist ein intelligenter Zeiger mit Referenzzählung, der durch Klonen gemeinsam genutzt wird. Jedes Mal, wenn Sie eine klonen Arc, wird die Referenzanzahl auf die zugrunde liegenden Daten erhöht, die zugrunde liegenden Daten bleiben jedoch unverändert.
Das passiert also in Ihrem Beispiel. Die Elemente des Vektors sind unterschiedliche Zeiger auf denselben HashMap.