Modul 9 — Lifetimes
Referenzen im Griff: longest
Der Klassiker, der nicht kompiliert — und dich das wichtigste Konzept von Rust vollständig begreift:
fn longest(x: &str, y: &str) -> &str {
if x.len() > y.len() {
x
} else {
y
}
}
Der Compiler lehnt ab (E0106: fehlende Lifetime-Spezifikation). Warum?
Die Rückgabe kommt mal von x, mal von y — der Compiler kann beim
Signatur-Lesen nicht wissen, wie lange die Ergebnisse gültig bleiben.
Die Lösung: eine Lifetime-Annotation als Vertrag:
fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
if x.len() > y.len() {
x
} else {
y
}
}
fn main() {
let s1 = String::from("langer String");
let s2 = String::from("kurz");
let result = longest(s1.as_str(), s2.as_str());
println!("länger: {result}");
}
Gelesen: "'a bezeichnet die Spanne, in der beide Eingaben gültig sind —
und das Ergebnis lebt höchstens so lange." Wichtig: Die Annotation
ändert nichts zur Laufzeit. Sie ist reine Compile-Zeit-Dokumentation,
an der der Borrow-Checker jeden Aufruf misst. Hätte s2 den Block nicht
überlebt, in dem result benutzt wird, wäre der Aufruf abgelehnt worden.
Was Lifetimes sind — und was nicht
- Kein Garbage Collector, kein Laufzeitsystem — nur Prüfregeln
- Sie ändern nicht, WIE lange Referenzen leben, sondern BESCHREIBEN es
- Der Lohn: dangling Pointer sind in safe Rust unmöglich
Übung: der Vertrag fehlt
🧩 Übung m9-l1-e1
🔮 Vorhersage: Was passiert beim Ausführen?
✅ Wichtige Erkenntnisse
Haken setzen, um deinen Lernfortschritt zu markieren:
Elision: meistens schreibst du nichts
Gute Nachricht: In echtem Code stehen Lifetime-Annotationen selten. Das liegt an den Elisionsregeln — Mustern, die der Compiler automatisch anwendet:
- Jede Referenz als Parameter bekommt ihre eigene Lifetime
- Gibt es genau eine Eingabe-Referenz, bekommt die Ausgabe ihre Lifetime
- Bei einer Methode mit
&selfbekommt die Ausgabe die von self
Deshalb kompiliert das ohne eine einzige Annotation:
fn first_word(s: &String) -> &str {
for (i, &b) in s.as_bytes().iter().enumerate() {
if b == b' ' {
return &s[0..i];
}
}
s.as_str()
}
fn main() {
let satz = String::from("erstes Wort folgt");
println!("erstes Wort: {}", first_word(&satz));
}
Eine Eingabe-Referenz, eine Ausgabe — Regel 2 verbindet sie. Genau deshalb
hatten unsere Funktionen der letzten Module nie Annotations-Ballast:
&str rein, &str raus, der Checker validiert still jede Zeile.
Explizit schreiben musst du, wenn zwei Eingaben um die Ausgabe
konkurrieren — wie bei longest.
📝 Schnellprüfung
Warum braucht first_word keine Lifetime-Annotation?
Übung: aufräumen mit Elision
🧩 Übung m9-l2-e1
🔮 Vorhersage: Was passiert beim Ausführen?
✅ Wichtige Erkenntnisse
Haken setzen, um deinen Lernfortschritt zu markieren:
Structs mit Lifetimes & 'static
Structs besitzen Daten — aber sie können auch nur leihen. Hält ein Struct eine Referenz, braucht es selbst eine Lifetime: jede Instanz ist an die geliehenen Daten gebunden und stirbt mit ihnen.
struct Excerpt<'a> {
part: &'a str,
}
impl<'a> Excerpt<'a> {
fn new(text: &'a str, up_to: usize) -> Excerpt<'a> {
Excerpt {
part: &text[..up_to.min(text.len())],
}
}
}
fn main() {
let roman = String::from("Rust: sicher und schnell");
let ex = Excerpt::new(&roman, 4);
println!("Auszug: {}", ex.part);
}
Excerpt<'a> heißt: "Auszug Nr. 1 leiht von Daten, die mindestens solange
leben wie der Auszug benutzt wird." Würdest du roman droppen und ex
danach lesen, stoppt der Compiler mit E0505 — das Original ist schon weg,
bevor der Auszug es gebraucht hätte.
Ein Sonderfall verdient seinen Namen: 'static — die Lifetime des gesamten Programmlaufs. String-Literale sind der häufigste Vertreter:
fn motto() -> &'static str {
"sicher, schnell, produktiv"
}
fn main() {
println!("{}", motto());
}
Das Literal steht im Binärfile — es kann nicht "wegfallen", daher darf die Referenz ewig leben. Alles, was zur Laufzeit entsteht (String::from, Dateien, Netzwerk), lebt kürzer und bekommt entsprechend kürzere Lifetimes.
Wann brauche ich 'a am Struct?
- Nur wenn ein Feld eine REFERENZ ist — owned Felder (String, Vec) brauchen nichts
- Die Lifetime am Struct ist eine Verpflichtung, keine Option
- 'static kommt fast nur bei Literalen und gepooltem Text vor
Übung: der Auszug
🧩 Übung m9-l3-e1
🔮 Vorhersage: Was passiert beim Ausführen?
✅ Wichtige Erkenntnisse
Haken setzen, um deinen Lernfortschritt zu markieren:
Mini-Projekt: Textwerkstatt
Das Abschlussprojekt des Moduls: eine Textwerkstatt, die ohne eine einzige Kopie auskommt — alles sind Slices ins Original. Für den Einstieg das Szenario:
🏢 Praxis-Szenario: Der Log-Analysator
Dein Team sichtet riesige Logdateien: Welche Zeile ist die längste? Wie viele Wörter hat sie? Der bisherige Ansatz kopiert jede Zeile in neue Strings — Millionen Allokationen, halbe Minute Laufzeit, für eine Antwort, die der Betrachter längst vergessen hat. Du schlägst vor: Referenzen statt Kopien — der Originaltext bleibt, wo er ist, die Analyse arbeitet mit Slices.
🧩 Übung m9-l4-e1
🔮 Vorhersage: Was passiert beim Ausführen?
Was du in Modul 9 geschafft hast
- Lifetimes als Verträge gelesen und geschrieben — dort, wo der Checker sie braucht
- Elisionsregeln nutzen: der Normalfall braucht keine Annotation
- Structs an geliehene Daten gebunden; 'static für Programmlang-Lebendes
- Eine Analyse-Bibliothek ohne eine einzige Allokation im Hot Path
✅ Wichtige Erkenntnisse
Haken setzen, um deinen Lernfortschritt zu markieren:
Modul-Checkpoint
Checkpoint: Modul 9
Bestehensgrenze: 80 %. Der Versuch wird bewertet und zählt für das Modul-Gate.
Bereit, dein Wissen zu testen?
Probiere unsere Übungsprüfungen mit Hunderten von realistischen Fragen aus.
Üben starten →