Geschichte der Frage:
Im Vergleich zu nativen Sprachen (C/C++) ermöglicht Rust eine sichere Arbeit mit Zeichenfolgen durch eine strikte Trennung zwischen referenzierten (&str) und besitzenden (String) Typen. Dies beseitigt die meisten Fehler, die mit falschem Speicher, Pufferüberlauf und Double-Free verbunden sind.
Problem:
Im Gegensatz zu "großen" GC-Sprachen, in denen jede Zeichenfolge im verwalteten Speicher lebt, muss man in Rust genau verstehen, wer die Zeichenfolge besitzt, wie lange sie lebt und wie man keine dangling references nach Modifikationen erhält. Die Arbeit mit UTF-8-Zeichenfolgen erfordert Vorsicht beim Indizieren und Ändern.
Lösung:
In Rust ist String eine veränderbare, heap-allokierte Zeichenfolge, die ihren Inhalt besitzt. &str ist ein unveränderlicher Verweis auf eine Folge von Bytes mit der Garantie UTF-8. Bei Bedarf kann man sicher konvertieren (&str -> String und zurück) mit Hilfe von Methoden aus der Standardbibliothek.
Beispielcode:
fn main() { let owned: String = String::from("Rust"); let borrowed: &str = &owned; let primitive: &str = "Hello"; // Literale sind immer &str // Konvertierung von &str -> String let s: String = primitive.to_string(); // Konvertierung von String -> &str let st: &str = &s; println!("{} {} {} {}", owned, borrowed, primitive, st); }
Schlüsselmerkmale:
&'static str und nicht StringWarum kann man eine Zeichenfolge nicht wie s[1] oder s[i] indizieren?
Rust verwendet UTF-8 für Zeichenfolgen, daher ist die Indizierung nicht direkt verfügbar: s[i] gibt nicht das i-te Zeichen zurück und kann manchmal zu einem Panic führen, wenn man außerhalb der Grenzen von Bytes zugreift. Stattdessen sollten Sie die Methoden .chars().nth(i) oder .get(start..end) verwenden.
Kann man &str sicher modifizieren?
Nein - &str ist immer ein unveränderliches Slice. Für Modifikationen verwenden Sie to_owned/to_string oder nutzen Sie String/Vec<u8>.
Was ist der wesentliche Unterschied zwischen String::from("abc") und "abc".to_string()?
Diese Varianten sind in Bezug auf das Ergebnis äquivalent, beide erstellen eine String durch Kopieren von Daten aus &str. Der Unterschied liegt nur im Stil: zum Beispiel, to_string ist über das Trait ToString implementiert, während String::from klarer den Intent ausdrückt, "Besitz zu schaffen".
Die Funktion nahm eine String entgegen und führte eine unnötige Kopie der Zeichenfolge innerhalb durch (clone), schrieb dann ein Slice in eine andere Funktion, ohne die Lebensdauer der Quelle zu verlängern. Ergebnis: dangling reference & Absturz.
Vorteile:
Nachteile:
Die Funktion akzeptiert &str, wenn Modifikationen benötigt werden - innerhalb wird .to_string() aufgerufen, während die gesamte Logik "zero copy" bleibt. Lebensdauern sind unter Kontrolle, keine überflüssige Allokation.
Vorteile:
Nachteile: