In Rust implementieren die Standard-Sammlungen (wie Vec<T>, HashMap<K,V>, HashSet<T> usw.) das Prinzip des Eigentums an ihren Inhalten. Das bedeutet, dass die Sammlung alle Objekte, die sie enthält, besitzt und für die Freigabe ihres Speichers bei der Entfernung verantwortlich ist.
Zum Beispiel werden die Elemente, die in einen Vec<T> eingefügt werden, in den Vektor verschoben (move), der anschließend Eigentum an ihnen hat:
let s = String::from("hi"); let mut v = Vec::new(); v.push(s); // s ist jetzt verschoben, nicht verfügbar
Wenn die Sammlung kopierbare Werte enthält, werden sie kopiert; wenn es sich um verschiebbare handelt, werden die Eigentumsrechte übertragen. Elemente oder die Sammlung müssen geklont werden, wenn das ursprüngliche Wert an zwei Orten erhalten bleiben soll, zum Beispiel:
let name = String::from("Olga"); let mut v = Vec::new(); v.push(name.clone()); println!("{}", name); // name ist weiterhin verfügbar, da es geklont wurde
Was passiert beim Einfügen eines Elements in eine HashMap, wenn ein verschiebbarer Datentyp (z.B. String) als Schlüssel verwendet wird? Wird der ursprüngliche Schlüssel nach seiner Übergabe an HashMap::insert() weiterhin verfügbar sein?
Oft wird die falsche Antwort gegeben: "Der ursprüngliche Schlüssel bleibt nach dem Einfügen verfügbar".
Tatsächlich wird das Eigentum des Schlüssels und des Wertes an die HashMap übertragen, und nach dem Einfügen können sie nicht ohne vorheriges Klonen verwendet werden:
let key = String::from("id"); let mut map = std::collections::HashMap::new(); map.insert(key, 42); // key ist nicht mehr verfügbar
Ein Versuch, auf key zuzugreifen, wird einen Kompilierungsfehler verursachen.
Geschichte Ein Entwickler versuchte, ein nach dem Einfügen in den Vec verschobenes Objekt zu verwenden und erhielt den Fehler "value used here after move", ohne zu verstehen, dass der Vector jetzt Eigentum daran hat.
Geschichte Bei der Arbeit mit HashMap wurde vergessen, die Schlüsselnamen zu klonen, was dazu führte, dass sie an anderen Stellen nicht verwendet werden konnten, was eine erhebliche Umstrukturierung des Codes erforderte.
Geschichte In einem der Projekte wurde versucht, einen Verweis auf ein internes Element des Vektors außerhalb der Funktion zurückzugeben, wobei vergessen wurde, dass der Verweis bei einer Änderung der Größe des Vektors ungültig wird. Dies führte zu dangling references und einem Crash während der Ausführung (panic).