Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Praxisteil & Übungen: Speicherverwaltung, Ownership und Referenzen

Dieser Praxisteil führt Sie Schritt für Schritt durch das Verständnis von Besitzrechten (Ownership) und Ausleihen (Borrowing) in Rust.

1. Praxis-Szenario: Das Transaktions-Verarbeitungsmodul eines Banksystems

Sie arbeiten als Entwickler bei einer Bank. Sie schreiben ein Modul zur Erfassung von Überweisungen, das Daten ressourcenschonend liest und den Verarbeitungsstatus modifiziert.

Die Übungsaufgabe befindet sich im Verzeichnis:


2. Strukturierte Praxis-Einheiten

2.1 Get Started: Ownership & Move-Semantik

In Rust besitzt eine Variable einen Wert und der Besitz wird bei Zuweisungen standardmäßig übertragen (Move).

Beispiel:

#![allow(unused)]
fn main() {
let s1 = String::from("Rust");
let s2 = s1; // s1 ist ab hier ungültig!
}

Erklärung:

  • String::from: Erstellt ein String-Objekt auf dem Heap.
  • let s2 = s1: Überträgt das Besitzrecht von s1 auf s2, um Double-Free-Fehler beim Verlassen des Gültigkeitsbereichs zu verhindern.

Aufgabe: Deklarieren Sie in Ihrer main()-Funktion eine String-Variable s1 mit dem Wert "Rust".


2.2 Unveränderliches Ausleihen (Referenzen &)

Referenzen ermöglichen es, Werte auszuleihen, ohne dass der Besitz übertragen wird.

Beispiel:

#![allow(unused)]
fn main() {
fn anzeigen(s: &String) {
    println!("{}", s);
}
}

Erklärung:

  • &String: Typ einer unveränderlichen Referenz auf einen String. Der Besitzer bleibt die aufrufende Funktion.

Aufgabe:

  1. Schreiben Sie eine Funktion anzeigen, die eine unveränderliche String-Referenz (&String) als Parameter entgegennimmt und diese ausgibt.
  2. Rufen Sie anzeigen in main() mit einer Referenz auf s1 (&s1) auf und geben Sie s1 danach erneut in main() aus.

2.3 Veränderbares Ausleihen (&mut)

Um geliehene Werte zu modifizieren, müssen Sie eine veränderliche Referenz deklarieren.

Beispiel:

#![allow(unused)]
fn main() {
fn hinzufuegen(s: &mut String) {
    s.push_str("pfad");
}
}

Erklärung:

  • &mut String: Typ einer veränderlichen Referenz. Es darf zu jedem Zeitpunkt nur genau eine veränderliche Referenz existieren.

Aufgabe:

  1. Schreiben Sie eine Funktion hinzufuegen, die eine veränderliche String-Referenz (&mut String) als Parameter entgegennimmt und über s.push_str("pfad") Text anhängt.
  2. Deklarieren Sie in main() eine veränderbare String-Variable s2 mit dem Wert "Lern".
  3. Rufen Sie hinzufuegen mit einer veränderlichen Referenz auf s2 (&mut s2) auf und geben Sie s2 danach aus.

3. Genaue Code-Erklärung der Musterlösung

Der fertige Code der Musterlösung befindet sich unter solutions/02_ownership/src/main.rs:

1: // Musterlösung zu Übung 2: Ownership & Borrowing
2: // Alle Anforderungen wurden erfolgreich implementiert.
3: 
4: fn main() {
5:     // 1. Zuweisung und Übergabe als unveränderliche Referenz (&String)
6:     let s1 = String::from("Rust");
7:     anzeigen(&s1); // Wir übergeben nur eine Referenz (kein Ownership-Transfer)
8:     println!("Der String '{}' ist nach dem Anzeigen immer noch gültig!", s1);
9: 
10:    // 2. Erstellen und Übergabe einer veränderlichen Referenz (&mut String)
11:    let mut s2 = String::from("Lern");
12:    hinzufuegen(&mut s2); // Wir verleihen veränderbaren Zugriff
13:    println!("Geändertes Wort: {}", s2);
14: }
15: 
16: // NIMMT REFERENZ ENTGEGEN: s hat den Typ &String
17: fn anzeigen(s: &String) {
18:     println!("Wort: {}", s);
19: }
20: 
21: // NIMMT VERÄNDERLICHE REFERENZ ENTGEGEN: s hat den Typ &mut String
22: fn hinzufuegen(s: &mut String) {
23:     s.push_str("pfad");
24: }

Zeilen-Analyse der Lösung:

  • Zeile 6: let s1 = String::from("Rust"); – Deklariert das String-Objekt auf dem Stack, welches auf den Heap-Speicher zeigt.
  • Zeile 7: anzeigen(&s1); – Leiht s1 unveränderlich aus. Da der Besitz nicht übertragen wird, bleibt s1 in main() gültig.
  • Zeile 11: let mut s2 = String::from("Lern"); – Erstellt eine veränderbare String-Variable auf dem Stack.
  • Zeile 12: hinzufuegen(&mut s2); – Übergibt eine veränderbare Referenz an hinzufuegen.
  • Zeile 17–19: Die Funktion anzeigen liest den Wert über s aus. Nach dem Funktionsende wird nur die Referenz vom Stack gelöscht.
  • Zeile 21–24: Die Funktion hinzufuegen greift über s direkt auf den Heap-Speicher von s2 zu und hängt die Bytes "pfad" an.