Wann erstellt `vec!` Verschiedene Elemente oder nicht?

Oct 21 2020

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

9 kmdreko Oct 21 2020 at 14:06

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äßigen CloneImplementierung 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.

3 PeterHall Oct 21 2020 at 14:03

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.