Direkt zum Hauptinhalt springen
eLearner.app
Modul 3 · Lektion 2 von 26/14 im Kurs~15 min
Lektionen des Moduls (2/2)

Referenzen und Borrowing

In Rust kann die ständige Übergabe des Besitzes (Ownership) einer Variablen an eine Funktion und deren Rückgabe sehr umständlich sein. Um dieses Problem zu lösen, verwendet Rust Referenzen (references).

Das Erstellen einer Referenz auf einen Wert wird als Borrowing (Ausleihen) bezeichnet.

Unveränderliche Referenzen

Eine Referenz wird deklariert, indem das Symbol & vor den Typ oder die Variable gestellt wird. Standardmäßig sind Referenzen unveränderlich (immutable): Sie erlauben das Lesen des Wertes, aber nicht dessen Modifikation.

Code
fn main() {
    let s1 = String::from("hello");

    // Passiamo un riferimento a s1, non l'ownership
    let len = calculate_length(&s1);

    // s1 è ancora utilizzabile qui!
    println!("La lunghezza di '{}' è {}.", s1, len);
}

fn calculate_length(s: &String) -> usize { // s è un riferimento a una String
    s.len()
} // Qui s esce dallo scope, ma poichè non possiede il valore, non succede nulla

Veränderliche Referenzen

Wenn Sie einen ausgeliehenen Wert ändern müssen, müssen Sie eine veränderliche Referenz über &mut verwenden. Die ursprüngliche Variable muss ebenfalls als veränderlich mit mut deklariert werden:

Code
fn main() {
    let mut s = String::from("hello");

    // Passiamo un riferimento mutabile
    change(&mut s);

    println!("{}", s); // Stampa "hello, world"
}

fn change(some_string: &mut String) {
    some_string.push_str(", world");
}

Die goldenen Regeln des Borrowings

Um Speicherbeschädigungen und Race Conditions (Datenrennen) zur Compilezeit zu verhindern, stellt Rust zwei grundlegende Regeln auf:

  1. Sie können beliebig viele unveränderliche Referenzen (&T) auf einen Wert zur gleichen Zeit haben.
  2. ODER Sie können genau eine veränderliche Referenz (&mut T) auf einen Wert auf einmal haben.

Sie können unveränderliche und veränderliche Referenzen für denselben Wert im selben Gültigkeitsbereich absolut nicht mischen:

Code
let mut s = String::from("hello");

let r1 = &s; // Valido
let r2 = &s; // Valido
// let r3 = &mut s; // ERRORE DI COMPILAZIONE! Non puoi creare &mut s se s è già presa in prestito come immutabile

Der Gültigkeitsbereich von Referenzen und Non-Lexical Lifetimes (NLL)

In der Vergangenheit dauerte der Gültigkeitsbereich einer Referenz zwingend bis zum Ende des Blocks, in dem sie erstellt wurde. Heute ist der Rust-Compiler dank Non-Lexical Lifetimes (NLL) intelligenter: Der Gültigkeitsbereich einer Referenz endet in der letzten Zeile, in der sie verwendet wird, nicht notwendigerweise am Blockende.

Dies macht den folgenden Code gültig:

Code
let mut s = String::from("hello");
let r1 = &s;
let r2 = &s;
println!("{} e {}", r1, r2); // Ultimo uso di r1 e r2. I riferimenti immutabili scadono qui!

let r3 = &mut s; // Valido! Nessun riferimento immutabile è attivo a questo punto

Probiere es aus

Übung#rust.m3.l2.e1
Versuche: 0Wird geladen…

Übergeben Sie eine unveränderliche Referenz von s1 an die Funktion calculate_length unter Verwendung des Symbols &.

Editor wird geladen…
Hinweis anzeigen

Ersetzen Sie `/* TODO \_/`durch`&s1`, um eine unveränderliche Referenz auf den String zu übergeben.

Lösung nach 3 Versuchen verfügbar

Übung#rust.m3.l2.e2
Versuche: 0Wird geladen…

Machen Sie die Variable s veränderlich (let mut s) und übergeben Sie eine veränderliche Referenz (&mut s) an die Funktion change, um ihr die Änderung des Strings zu ermöglichen.

Editor wird geladen…
Hinweis anzeigen

Verwenden Sie `let mut s`anstelle von`let s`und rufen Sie`change(&mut s);` auf.

Lösung nach 3 Versuchen verfügbar

Übung#rust.m3.l2.e3
Versuche: 0Wird geladen…

Deklarieren Sie eine Variable s, die String::from("Rust") enthält. Erstellen Sie zwei verschiedene unveränderliche Referenzen r1 und r2 auf s und geben Sie die beiden Referenzen schließlich durch ein Leerzeichen getrennt mit dem println!-Makro aus.

Editor wird geladen…
Hinweis anzeigen

Weisen Sie `let r1 = &s;` und `let r2 = &s;` zu, um zwei unveränderliche Referenzen zu erhalten, und geben Sie sie dann mit `println!("{} {}", r1, r2);` aus.

Lösung nach 3 Versuchen verfügbar