Zum Inhalt springen

Eigentümerschaft

Welche der folgenden Aussagen erklärt am besten, warum ein i32 ohne Verschiebung kopiert werden kann, ein String jedoch nicht?

Wenn ein String ohne Verschiebung kopiert werden könnte, dann könnten zwei Variablen glauben, denselben String zu besitzen, was zu einer doppelten Freigabe führen würde.


Der folgende Code-Snippet kompiliert nicht:

let s = String::from("Hello world");
let s_ref = &s;
let s2 = *s_ref;
println!("{s2}");

Welche der folgenden Aussagen beschreibt am besten das undefinierte Verhalten, das auftreten könnte, wenn dieses Programm ausgeführt werden dürfte?

Das println ist technisch sicher, da der String erst am Ende des aktuellen Gültigkeitsbereichs freigegeben wird. Aber dann tritt undefiniertes Verhalten auf, wenn der String im Namen von s und s2 zweimal freigegeben wird.


Das folgende Programm kompiliert nicht:

fn copy_to_prev(v: &mut Vec<i32>, i: usize) {
let n = &mut v[i];
*n = v[i - 1];
}
fn main() {
let mut v = vec![1, 2, 3];
copy_to_prev(&mut v, 1);
}

Welche der folgenden Aussagen beschreibt am besten das undefinierte Verhalten, das auftreten könnte, wenn dieses Programm ausgeführt werden dürfte?

Dieses Programm ist sicher. Es könnte kein undefiniertes Verhalten auftreten, wenn es ausgeführt würde. (Wenn i außerhalb der Grenzen von v läge, würde Rust zur Laufzeit paniken, anstatt undefiniertes Verhalten zu verursachen.)

Das Problem ist, dass Rust nicht sicher weiß, dass v[i] und v[i - 1] sich auf verschiedene Elemente beziehen.


Betrachten Sie diese Funktion, die eine vereinfachte Variante der Funktion aus dem vorherigen Quiz ist:

/// Fügt den Namen einer Person "Ph.D." hinzu
fn award_phd(name: &String) {
let mut name = *name;
name.push_str(", Ph.D.");
}

Der Rust-Compiler lehnt diese Funktion mit dem folgenden Fehler ab:

error[E0507]: cannot move out of `*name` which is behind a shared reference
--> test.rs:3:20
|
3 | let mut name = *name;
| ^^^^^
| |
| move occurs because `*name` has type `String`, which does not implement the `Copy` trait
| help: consider borrowing here: `&*name`

Angenommen, der Compiler hätte diese Funktion NICHT abgelehnt. 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”.

Die Anweisung let mut name = *name bewirkt, dass name die Ownership des Eingabestrings übernimmt. Der Aufrufer behält jedoch auch weiterhin die Ownership des Strings. Daher wird der String nach Beendigung von award_phd freigegeben. Jedes der oben genannten Programme weist daher undefiniertes Verhalten auf, da name schließlich ein zweites Mal freigegeben wird. Es spielt keine Rolle, ob name oder eine Referenz auf name nach dem Aufruf von award_phd gelesen wird.


fn main() {
let mut point = [0, 1];
let mut x = point[0];
let y = &mut point[1];
x += 1;
*y += 1;
println!("{} {}", point[0], point[1]);
}

Dieses Programm kompiliert, da die Bindung von x point[0] kopiert, wodurch y point[1] mutabel borgen kann. Die Mutation x += 1 beeinflusst point nicht, während die Mutation *y += 1 dies tut, sodass das Endergebnis 0 2 ist.