Storia della domanda
In Rust si distinguono due tipi di stringa principali — &str (slice di stringa, immutabile, frequentemente un letterale di stringa) e String (stringa dinamica, mutabile). Nelle prime fasi dello sviluppo del linguaggio, la scelta tra questi due tipi ha permesso di semplificare il lavoro con la memoria efficiente e garantire la sicurezza dei tipi durante la manipolazione dei dati testuali grazie a un rigido sistema di proprietà e riferimenti.
Problema
Molti sviluppatori si confondono quando interagiscono tra questi tipi. Ad esempio, un letterale di stringa è &'static str, ossia un riferimento a una stringa immutabile allocata durante la compilazione, mentre String può espandersi dinamicamente e contenere dati ottenuti a runtime. Si pongono domande su come convertire tra i tipi, utilizzare correttamente la proprietà e evitare copie superflue.
Soluzione
La conversione tra &str e String è trasparente se si comprendono le regole di base della proprietà:
String tramite riferimento (my_string.as_str()) o semplice prestito (&my_string).&str in String si può utilizzare to_string() oppure String::from().Esempio di codice:
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); }
Caratteristiche chiave:
&str non occupa memoria nel heap, è sempre immutabile.String alloca memoria dinamicamente, può essere modificata.Si può modificare un letterale di stringa in Rust?
No, un letterale di stringa (&'static str) è sempre immutabile; ogni tentativo di modificare un carattere darà errore in fase di compilazione.
È sufficiente chiamare .to_string() su &str per ottenere una stringa mutabile senza copie superflue?
No, .to_string() alloca sempre nuova memoria e copia il contenuto. Questo è inevitabile se si ha bisogno di una stringa mutabile basata su uno slice.
Si può ottenere un riferimento &str da String senza rischio di perdita del tempo di vita?
Sì, il riferimento ottenuto in questo modo (let s: &str = &my_string;) vive non più a lungo della String originale. Tentare di restituire &str da una String locale in una funzione genererà un errore di tempo di vita.
&str su un String temporaneo che esce dallo scope&str in String senza necessità (allocazioni superflue)String::from("text") non creerà una copia dei datiLa funzione restituisce &str che punta a un String temporaneo all'interno della funzione:
fn faulty() -> &str { let s = String::from("Oops"); &s // errore di tempo di vita! }
Vantaggi:
Svantaggi:
La funzione restituisce immediatamente un String e trasferisce la proprietà al chiamante:
fn correct() -> String { String::from("Safe!") }
Vantaggi:
Svantaggi: