Achtergrond
In Rust onderscheiden we twee hoofdstringtypes — &str (een string slice, onveranderlijk, vaak stringliteral) en String (dynamische, veranderlijke string). In de vroege stadia van de taalontwikkeling maakte de keuze tussen deze twee het mogelijk om de interactie met efficiënte geheugenwerking te vereenvoudigen en typeveiligheid te waarborgen bij de verwerking van tekstgegevens, dankzij het strikte eigenaarschap- en referentiesysteem.
Probleem
Veel ontwikkelaars raken in de war bij de interactie tussen deze types. Bijvoorbeeld, een stringliteral is een &'static str, dat wil zeggen een verwijzing naar een onveranderlijke string die tijdens de compilatie is toegewezen, terwijl String dynamisch kan groeien en gegevens kan bevatten die tijdens runtime zijn verkregen. Er rijzen vragen over hoe te converteren tussen types, het juiste gebruik van eigenaarschap en het vermijden van overbodige kopieën.
Oplossing
Conversie tussen &str en String is transparant als je de basisregels van eigenaarschap begrijpt:
String halen via een referentie (my_string.as_str()) of eenvoudig lenen (&my_string).&str omzetten in String met to_string() of String::from().Codevoorbeeld:
fn main() { let s_literal: &str = "hello"; let s_string: String = String::from(s_literal); let s_slice: &str = &s_string; let new_string = s_slice.to_string(); println!("{} {}", s_string, new_string); }
Belangrijke kenmerken:
&str gebruikt geen heap-geheugen, altijd onveranderlijk.String — allocateert geheugen dynamisch, kan worden gewijzigd.Kan je een stringliteral in Rust wijzigen?
Nee, een stringliteral (&'static str) is altijd onveranderlijk, elke poging om een teken te wijzigen leidt tot een compilatiefout.
Is het genoeg om .to_string() aan te roepen op &str om een veranderlijke string te krijgen zonder overbodige kopieën?
Nee, .to_string() alloceert altijd nieuw geheugen en kopieert de inhoud. Dit is onvermijdelijk als een veranderlijke string op basis van een slice nodig is.
Kan je een verwijzing &str uit String krijgen zonder risico op levensduurlekkage?
Ja, de verwijzing die op deze manier wordt verkregen (let s: &str = &my_string;), leeft niet langer dan de oorspronkelijke String. Proberen om &str op een lokale String uit een functie terug te geven, zal een fout opvoeren van levensduur.
&str naar een tijdelijk String dat buiten de scope valt&str naar String omzetten zonder noodzaak (overbodige allocaties)String::from("text") geen kopie van gegevens maaktEen functie retourneert &str, verwijzend naar een tijdelijk String binnen de functie:
fn faulty() -> &str { let s = String::from("Oops"); &s // fout van levensduur! }
Voordelen:
Nadelen:
De functie retourneert direct een String en geeft het eigenaarschap aan de caller:
fn correct() -> String { String::from("Safe!") }
Voordelen:
Nadelen: