Borrowing
Fehlendes mutables Borrowing
Abschnitt betitelt „Fehlendes mutables Borrowing“fn incr(n: &mut i32) { *n += 1;}
fn main() { let mut n = 1; incr(&n); println!("{n}");}Obwohl n als mut markiert ist, muss die Referenz auf n ebenfalls als mut markiert werden. Eine gültige Version dieses Programms würde also incr(&mut n) lauten.
Inkompatible Referenzen
Abschnitt betitelt „Inkompatible Referenzen“fn main() { let mut s = String::from("hello"); let s2 = &s; let s3 = &mut s; s3.push_str(" world"); println!("{s2}");}Es ist unzulässig, eine mutable Referenz auf einen Wert (s3) zu verwenden, während eine immutable Referenz (s2) noch aktiv ist.
Undefined Behavior Vektor
Abschnitt betitelt „Undefined Behavior Vektor“Betrachten Sie diese Rust-Funktion, die eine Zahl an das Ende eines Vektors anhängt und dann die Zahl vom Anfang des Vektors entfernt und zurückgibt:
fn give_and_take(v: &Vec<i32>, n: i32) -> i32 { v.push(n); v.remove(0)}Normalerweise, wenn Sie versuchen, diese Funktion zu kompilieren, gibt der Compiler den folgenden Fehler zurück:
error[E0596]: cannot borrow `*v` as mutable, as it is behind a `&` reference --> test.rs:2:5 |1 | fn give_and_take(v: &Vec<i32>, n: i32) -> i32 { | --------- help: consider changing this to be a mutable reference: `&mut Vec<i32>`2 | v.push(n); | ^^^^^^^^^ `v` is a `&` reference, so the data it refers to cannot be borrowed as mutableNehmen Sie an, dass der Compiler diese Funktion NICHT abgelehnt hat. Wählen Sie jedes (falls zutreffend) der folgenden Programme aus, das bei Ausführung möglicherweise undefiniertes Verhalten verursachen könnte. Wenn keines dieser Programme undefiniertes Verhalten verursachen könnte, dann wählen Sie “Keines dieser Programme”.
Wie wir bereits in diesem Abschnitt gesehen haben, kann v.push(n) dazu führen, dass v seinen internen Inhalt neu zuweist, wodurch alle Referenzen auf die Elemente von v auf dem Heap ungültig werden. Daher führt der Aufruf von give_and_take(&v, 4) dazu, dass zuvor erstellte Elementreferenzen auf ungültigen Speicher zeigen. Die beiden Programme, die let n = &v[0] vor give_and_take binden, sind Kandidaten für undefiniertes Verhalten. let v2 = &v ist kein Kandidat, da eine Referenz auf den Container v durch die Mutation von v nicht tatsächlich ungültig wird.
Das Programm, das println!("{}", n) ausführt, verursacht undefiniertes Verhalten durch das Lesen des ungültigen Speichers. Das Programm, das println!("{}", k) ausführt, verursacht kein undefiniertes Verhalten, da es die ungültige Referenz nicht verwendet.