Wenn eine Variable an eine Funktion übergeben wird, kann sie entweder per Referenz (borrow, mit & oder &mut) oder durch Verschiebung (move, ohne Referenz) übergeben werden.
Borrow: Es wird eine Referenz auf die Daten übergeben. Die Daten bleiben nach dem Funktionsaufruf verfügbar, aber bei einer unveränderlichen Referenz darf der Inhalt nicht geändert werden, für eine veränderliche kann es nur eine aktive Referenz geben.
fn read_length(s: &String) -> usize { s.len() }
Move: Die Variable "zieht" vollständig in die Funktion um. Nach der Übergabe können Sie die ursprüngliche Variable nicht mehr verwenden – sie wurde verschoben, und jeder Zugriff führt zu einem Kompilierungsfehler.
fn destroy(s: String) { println!("{}", s); } // s wird beim Verlassen zerstört let s = String::from("world"); destroy(s); // s kann nicht mehr verwendet werden
Dies verhindert doppelte Speicherfreigaben und andere Besitzfehler.
Kann ich eine Variable verwenden, nachdem sie per Wertübergabe (move) an eine Funktion übergeben wurde?
Nein! Nach der Übergabe einer Variable durch Wert — z.B. String — wird die ursprüngliche Variable ungültig:
let s = String::from("abc"); consume(s); // s ist hier nicht mehr gültig println!("{}", s); // Kompilierungsfehler
Viele verwechseln dies mit dem Verhalten von Typen mit Copy (z.B. i32), wo die Variable nach der Übergabe weiterhin gültig bleibt.
Geschichte
Ein junger Programmierer schrieb eine Funktion zur Verarbeitung von Strings, die String anstelle von &String akzeptierte. Dadurch wurde der ursprüngliche String nach dem Funktionsaufruf nicht mehr zugänglich, was zu doppelten Beladungen und zusätzlichem Speicherbedarf im Logserver führte.
Geschichte
In einem Mikrodienst wurde eine kritische Ressource über move an verschiedene Threads übergeben, was zu Kompilierungsfehlern beim Zugriff auf diese Ressource im Haupt-Thread führte. Die Architektur musste dringend refaktoriert werden, damit die Ressource über Referenzen oder Wrapper wie Arc übergeben wurde.
Geschichte
Im internen Ereignisparser wurde eine Variable beim Verarbeiten von Daten schnell (move) in ein Closure übernommen, was dazu führte, dass Zugriffe außerhalb des Closures Kompilierungsfehler verursachten. Das Problem wurde erst während des Reviews bemerkt – es wurde ein Stil für die obligatorische Verwendung von borrow für Daten eingeführt, die länger als die lokale Funktion leben sollten.