Borrowing (Leihen) ist eines der zentralen Konzepte in Rusts Speichermodell und eng mit dem Ownership-System verknüpft. Anstatt Daten zu verschieben oder zu kopieren, können Daten durch Borrowing geliehen werden, was eine sichere und effiziente Speicherverwaltung ermöglicht.
In diesem Tutorial wird erklärt, was Borrowing in Rust ist, wie es funktioniert und wann es verwendet wird.
Borrowing ist ein mächtiges Konzept in Rust, das es erlaubt, Daten sicher zu leihen, ohne den Besitz zu übertragen. Es ermöglicht es, Speicher effizient zu verwalten und gleichzeitig sicherzustellen, dass keine ungültigen Referenzen entstehen. Die Unterscheidung zwischen unveränderlichem und veränderlichem Borrowing hilft dabei, die Datenkonsistenz zu gewährleisten und Datenraces zu verhindern.
In Rust besitzt jede Variable standardmäßig ihren Speicherbereich. Das bedeutet, wenn eine Variable erstellt wird, übernimmt sie den "Besitz" (Ownership) der Daten. Manchmal möchte man jedoch nur eine Referenz auf die Daten einer anderen Variable haben, ohne das Ownership zu übernehmen. Das nennt man Borrowing.
fn main() {
let s1 = String::from("Hello");
let s2 = &s1; // s2 "leiht" sich den Wert von s1
println!("{}, {}", s1, s2);
}
In diesem Beispiel wird eine Referenz (&s1
) verwendet, um Borrowing zu ermöglichen. Das bedeutet, dass s2
eine unveränderliche Referenz auf s1
ist, aber kein Eigentum an den Daten hat.
Rust unterscheidet zwischen unveränderlichem und veränderlichem Borrowing. Wenn eine unveränderliche Referenz (&T
) verwendet wird, darf der Wert nicht verändert werden, solange diese Referenz aktiv ist.
fn main() {
let s = String::from("Rust");
let r = &s; // unveränderliches Borrowing
println!("Referenz: {}", r);
}
Hier kann s
nicht verändert werden, solange die Referenz r
besteht. Unveränderliche Referenzen sind mehrfach erlaubt, solange der Wert nicht verändert wird.
Ein veränderliches Borrowing ermöglicht es, den Wert zu ändern. Allerdings erlaubt Rust immer nur eine veränderliche Referenz gleichzeitig. Diese Regel verhindert Datenraces und stellt sicher, dass nur eine Stelle den Wert verändern kann.
fn main() {
let mut s = String::from("Hello");
let r = &mut s; // veränderliches Borrowing
r.push_str(", world!");
println!("Verändert: {}", r);
}
In diesem Beispiel kann r
den Wert von s
verändern. Beachte, dass s
als mut
deklariert werden muss, um eine veränderliche Referenz zu erhalten.
Rust hat klare Regeln für Borrowing, die sicherstellen, dass es zu keinen Speicherfehlern kommt:
fn main() {
let mut s = String::from("Rust");
let r1 = &s; // unveränderliches Borrowing
let r2 = &mut s; // veränderliches Borrowing - Fehler!
println!("{}, {}", r1, r2);
}
In diesem Fall entsteht ein Kompilierfehler, da unveränderliche und veränderliche Referenzen nicht gleichzeitig existieren dürfen.
Um sicherzustellen, dass eine Referenz nicht länger lebt als der Wert, auf den sie zeigt, verwendet Rust Lebensdauern (Lifetimes). Lebensdauern stellen sicher, dass keine ungültigen Referenzen existieren.
fn main() {
let s1 = String::from("Hello");
let r;
{
let s2 = String::from("World");
r = &s2; // Fehler: s2 lebt nicht lange genug
}
println!("Referenz: {}", r);
}
Dieser Code erzeugt einen Fehler, weil s2
in einem inneren Block deklariert wird und nach diesem Block nicht mehr existiert. Rust verhindert, dass r
auf eine ungültige Referenz zeigt.
Finden Sie interessante und zum Thema passende Kurse
Dieses 5-tägige Rust-Seminar bietet eine fundierte Einführung in die Grundlagen von Rust, darunter Speicherverwaltung (Ownership, Borrowing), der Standardbibliothek und Fehlerbehandlung. Die Teilnehmer lernen, wie man sauberen und sicheren Rust-Code schreibt, Module importiert und die umfangreichen Funktionen der Rust-Standardbibliothek nutzt.
5 Tage Vollzeit Online
Nächster Termin: 20. Januar 2025
Preis pro Person: 1900,00 EUR
Rabattaktion: 3 für den Preis von 2!
Schreiben Sie uns an, vielleicht finden wir eine Möglichkeit.
Nutzen Sie dazu unser Kontaktformular.