Lektionen des Moduls (1/2)
Lifetimes und Referenzen
In Rust hat jede Referenz eine Lebensdauer (Lifetime). Dies entspricht dem Gültigkeitsbereich (Scope), innerhalb dessen diese Referenz gültig ist. Meistens sind Lebensdauern implizit und werden vom Compiler dank der Elisionsregeln abgeleitet. Wenn jedoch die Beziehung zwischen den Lebensdauern verschiedener Referenzen mehrdeutig ist, müssen wir sie explizit deklarieren.
Das Hauptziel von Lebensdauern besteht darin, hängende Referenzen (Dangling References) zu verhindern (Referenzen auf Daten, die bereits aus dem Speicher freigegeben wurden).
Die Syntax von Lebensdauer-Annotationen
Die Namen von Lebensdauern beginnen mit einem Apostroph (') und werden normalerweise in sehr kurzen Kleinbuchstaben geschrieben (wie 'a). Lebensdauer-Annotationen ändern nicht die tatsächliche Lebensdauer von Variablen, sondern zeigen dem Compiler die Gültigkeitsbeziehung zwischen den empfangenen und eventuell zurückgegebenen Referenzen an.
Wenn beispielsweise eine Funktion zwei Parameter erhält, die Referenzen auf einen String sind, und eine Referenz auf einen String zurückgibt, und wir möchten, dass die zurückgegebene Referenz gültig ist, solange beide Eingabeparameter gültig sind, verwenden wir:
fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
if x.len() > y.len() {
x
} else {
y
}
}
Lebensdauer in Datenstrukturen
Wenn eine Datenstruktur ein Feld enthält, das eine Referenz ist, müssen wir die Lebensdauer auf dieser Referenz explizit annotieren. Dadurch wird garantiert, dass die Instanz der Struct die Daten, auf die sie verweist, nicht überleben kann:
struct ImportantExcerpt<'a> {
part: &'a str,
}
fn main() {
let novel = String::from("Chiamami Ismaele. Alcuni anni fa...");
let first_sentence = novel.split('.').next().unwrap();
let i = ImportantExcerpt {
part: first_sentence,
};
}
Die statische Lebensdauer
Die Lebensdauer 'static ist eine spezielle Lebensdauer, die die gesamte Ausführungsdauer des Programms überdauert. Alle String-Literale (&str) haben implizit eine 'static-Lebensdauer, da sie direkt in die Binärdatei kodiert sind.
let s: &'static str = "Ho un lifetime statico.";
Probiere es aus
Übung 1: Die longest-Funktion
Schreiben Sie eine Funktion namens longest<'a>, die zwei Parameter akzeptiert, x vom Typ &'a str und y vom Typ &'a str, und einen Wert vom Typ &'a str zurückgibt. Verwenden Sie innerhalb der Funktion ein if/else-Konstrukt, um den Parameter x zurückzugeben, wenn seine Länge größer als die von y ist, andernfalls y.
Hinweis anzeigen
Deklarieren Sie die Signatur mit `fn longest<'a>(x: &'a str, y: &'a str) -> &'a str`. Verwenden Sie dann `if x.len() > y.len() { x } else { y }`.
Lösung nach 3 Versuchen verfügbar
Übung 2: Strukturen mit Referenzen
Definieren Sie eine Struktur namens Excerpt<'a>, die ein einzelnes Feld namens part vom Typ &'a str enthält. Erstellen Sie in der main-Methode eine String-Variable namens text und instanziieren Sie eine Variable excerpt vom Typ Excerpt, indem Sie eine Referenz auf text übergeben. Geben Sie excerpt.part auf dem Bildschirm aus.
Hinweis anzeigen
Verwenden Sie `struct Excerpt<'a> { part: &'a str }`. Instanziieren Sie sie in main mit `Excerpt { part: &text }`.
Lösung nach 3 Versuchen verfügbar
Übung 3: Statische Referenzen
Deklarieren Sie eine Variable namens message mit expliziter Typannotation für die statische Lebensdauer (&'static str) und weisen Sie ihr ein String-Literal zu. Geben Sie den Wert von message aus.
Hinweis anzeigen
Verwenden Sie die Syntax `let message: &'static str = 'Messaggio statico!';`, um die statische Lebensdauer explizit zu annotieren.
Lösung nach 3 Versuchen verfügbar