String vs str in Rust: Warum Anfänger verwirrt sind und wie man es ein für alle Mal versteht
\n\nWenn Sie gerade erst anfangen, Rust zu lernen, sind Sie sicherlich schon auf folgende Situation gestoßen: Der Compiler meckert, Sie versuchen ein String dort zu übergeben, wo ein &str erwartet wird, oder umgekehrt. Kommt Ihnen bekannt vor? Dies ist eine der häufigsten Fragen auf Stack Overflow (tausende Aufrufe!), und das aus gutem Grund – das Thema ist wirklich grundlegend für das Verständnis der Speicherverwaltung in Rust.
In diesem Artikel werden wir uns ansehen, worin sich String und &str unterscheiden, wann welcher Typ verwendet werden sollte und wie man typische Fehler vermeidet. Los geht's!
Kurze Antwort für Eilige
\n\nWenn Sie es jetzt sofort brauchen – merken Sie sich das Wichtigste:
\n\n- \n
Stringist ein besitzender, veränderlicher, dynamischer Datentyp, der auf dem Heap gespeichert wird. \n&strist ein unveränderlicher String-Slice, der auf Daten verweist, die jemand anderem gehören. Meistens tritt er als&strauf. \n
Jetzt tauchen wir tiefer ein.
\n\nWas ist String in Rust?
\n\nString ist ein Typ, der Besitzer seiner Daten ist. Wenn Sie einen String erstellen, wird Speicher dafür auf dem Heap reserviert, und der String kann wachsen, schrumpfen oder verändert werden.
let mut s = String::from("Hallo");\ns.push_str(", Welt!");\nprintln!("{}", s); // Gibt aus: Hallo, Welt!\n\nHier ist s der Besitzer des Strings. Wenn s den Gültigkeitsbereich verlässt, wird der Speicher automatisch freigegeben (dank RAII – Resource Acquisition Is Initialization).
Hauptmerkmale von String:
\n- \n
- Besitzt die Daten (besitzender Typ) \n
- Veränderbar (mutable) \n
- Wird auf dem Heap gespeichert \n
- Kann aus einem String-Literal erstellt werden:
String::from("Text")\n - Unterstützt Verkettung, Einfügen, Löschen von Zeichen \n
Was ist &str in Rust?
\n\n&str (ausgesprochen als "Str-Slice" oder "String-Slice") ist ein Verweis auf eine Sequenz von UTF-8-Zeichen, die jemand anderem gehört. &str selbst ist lediglich ein Zeiger auf die Daten und die Länge.
let greeting: &str = "Hallo";\nprintln!("{}", greeting);\n\nIn diesem Beispiel ist greeting ein Verweis auf ein String-Literal, das direkt in der Binärdatei des Programms gespeichert ist (im Read-Only-Speichersegment). greeting besitzt diese Daten nicht – es zeigt nur darauf.
Hauptmerkmale von &str:
\n- \n
- Besitzt die Daten nicht (geliehener Typ) \n
- Unveränderbar (immutable) \n
- Wird entweder in der Binärdatei (String-Literale) oder auf dem Heap (als Slice eines
String) gespeichert \n - Leichtgewichtig – besteht aus zwei Feldern: Zeiger + Länge (16 Bytes auf einem 64-Bit-System) \n
- Ideal zur Übergabe an Funktionen, wenn der String nicht verändert werden muss
Hauptunterschiede zwischen String und &str (Tabelle)
\n\nFassen wir alles in einer übersichtlichen Tabelle zusammen:
\n\n| Merkmal | \nString | \n&str | \n
|---|---|---|
| Besitz | \nBesitzt die Daten | \nLeiht sich die Daten | \n
| Veränderbarkeit | \nJa (mut) | \nNein | \n
| Speicherort | \nHeap | \nHeap, Stack oder Binärdatei | \n
| Größe auf dem Stack | \n24 Bytes (ptr + len + cap) | \n16 Bytes (ptr + len) | \n
| Erstellung | \nString::from("...") | \n"..." oder &s[..] | \n
| Hauptverwendung | \nWenn der String verändert oder in
BlogsBuchempfehlungenLesen Sie auch |