Im vorherigen Kapitel hast du Ownership kennengelernt: jeder Wert hat genau einen Besitzer, und Move überträgt diesen Besitz. Aber: wenn jede Operation Ownership überträgt, wäre fast jedes Programm unschreibbar — Funktionen würden ihre Argumente verbrauchen, eine zweite Verwendung wäre nicht möglich. Die Lösung sind References und Borrowing: ein Wert kann temporär „verliehen" werden, ohne dass der Besitz wechselt. Dieses Kapitel zeigt die zwei Reference-Typen (&T, &mut T), die Regeln des Borrow Checkers, das subtile Konzept des Reborrowing, wie Dereferenzierung funktioniert — und schließt mit der Frage, warum Dangling References (Pointer auf freigegebenen Speicher) in Safe Rust per Definition unmöglich sind.
Warum References?
Stell dir vor, du willst die Länge eines Strings berechnen. Mit reiner Move-Semantik wäre das schmerzhaft:
fn laenge(s: String) -> (String, usize) {
let l = s.len();
(s, l) // gib s zurück, damit der Aufrufer es noch hat
}
fn main() {
let s = String::from("Hi");
let (s, l) = laenge(s); // Round-Trip-Move
println!("{s} hat {l} Bytes");
}Das ist verbose und alles andere als idiomatisch. Mit References geht es so:
fn laenge(s: &String) -> usize {
s.len()
}
fn main() {
let s = String::from("Hi");
let l = laenge(&s); // & — kein Move, nur Borrow
println!("{s} hat {l} Bytes"); // s ist weiterhin nutzbar
}Das & macht aus einer Move-Operation einen Borrow: die Funktion bekommt eine Referenz auf den Wert, nicht den Wert selbst. Der Besitzer bleibt der gleiche, und nach dem Funktions-Ende ist die Referenz weg — der Wert lebt weiter.
Die zwei Reference-Typen
Rust hat genau zwei Reference-Typen:
&T— eine shared (geteilte, lesende) Referenz. Mehrere&Tauf denselben Wert sind zur gleichen Zeit erlaubt. Der Wert kann durch ein&Tnicht mutiert werden.&mut T— eine exklusive (mutierende) Referenz. Genau eine&mut Tauf einen Wert. Solange sie lebt, gibt es keine andere Referenz (weder&Tnoch eine weitere&mut T) auf denselben Wert.
Diese zwei Regeln — beliebig viele &T ODER genau ein &mut T — sind das Aliasing-XOR-Mutability-Prinzip. Sie sind die Grundlage für:
- Memory-Safety: keine Pointer-Aliasing-Bugs.
- Compiler-Optimierungen:
&Tkann beliebig oft im Code als „lesen" angenommen werden. - Data-Race-Freiheit: Threads können
&Tparallel haben,&mut Tist exklusiv und damit thread-safe per Konstruktion.
Was dich erwartet
- Shared vs. Mut References — die zwei Reference-Typen im Detail, ihre Regeln und die typischen Stolperfallen für Einsteiger.
- Borrow Checker — wie der Compiler die Regeln zur Bauzeit prüft, die Non-Lexical-Lifetimes-Erweiterung, die wichtigsten Fehler-Codes
E0502,E0506,E0596mit ausführlicher Erklärung. - Reborrowing — das subtile Konzept, das dafür sorgt, dass
&mut-Referenzen in Funktions-Calls nicht „verbraucht" werden. Wann der Compiler implizit ein Reborrow einfügt und wann du es explizit machen musst. - Dereferenzierung und Auto-Deref — der
*-Operator, derDeref-Trait, und die mächtige Auto-Deref-Coercion, die&Stringzu&strmacht und Method-Calls über Smart-Pointers wieBox<T>transparent macht. - Dangling References — warum Pointer auf freigegebenen Speicher in Safe Rust unmöglich sind, der Einstieg in Lifetimes, und der Compiler-Fehler
E0597.
Was du nach diesem Kapitel kannst
&Tund&mut Tkorrekt in Funktions-Signaturen einsetzen.- Die Borrow-Checker-Regeln aus dem Stand erklären und in Compiler-Fehlern erkennen.
E0502-,E0506-,E0596-Fehlermeldungen lesen und systematisch beheben.- Reborrowing nachvollziehen — und wissen, wann du es explizit erzwingen musst.
- Die Auto-Deref-Coercion gezielt nutzen, um flexible APIs zu schreiben (
&strstatt&String,&[T]statt&Vec<T>). - Erkennen, warum eine Dangling Reference vom Compiler abgelehnt wird, und Lifetimes als Werkzeug zur Lösung verstehen.
Nach diesem Kapitel kommt der natürliche nächste Schritt: Slices als Spezial-Form von References, gefolgt von Structs, Enums und Pattern Matching — Themen, in denen References und Borrowing überall auftauchen.
Weiterführende Ressourcen
Externe Quellen
- The Rust Book – References and Borrowing
- Rust Reference – References
- The Rustonomicon – References
- Rust by Example – Borrowing