Storia della domanda:
Rispetto ai linguaggi nativi (C/C++), Rust costruisce una gestione sicura delle stringhe grazie a una netta separazione tra tipi di riferimento (&str) e tipi di possesso (String). Questo elimina la maggior parte degli errori relativi a problemi di memoria, overflow del buffer e double-free.
Problema:
A differenza dei linguaggi con GC avanzato, dove ogni stringa vive in memoria gestita, in Rust è fondamentale capire chi possiede la stringa, quanto a lungo vive e come evitare riferimenti pendenti dopo le modifiche. Lavorare con stringhe UTF-8 richiede attenzione durante l'indicizzazione e le modifiche.
Soluzione:
In Rust, String è una stringa mutabile, allocata nell'heap, che possiede il proprio contenuto. &str è un riferimento immutabile a una sequenza di byte con garanzia UTF-8. Se necessario, è possibile convertire in modo sicuro (&str -> String e viceversa) utilizzando i metodi std.
Esempio di codice:
fn main() { let owned: String = String::from("Rust"); let borrowed: &str = &owned; let primitive: &str = "Hello"; // literal è sempre &str // Conversione &str -> String let s: String = primitive.to_string(); // Conversione String -> &str let st: &str = &s; println!("{} {} {} {}", owned, borrowed, primitive, st); }
Caratteristiche principali:
&'static str, non StringPerché non si può indicizzare una stringa come s[1] o s[i]?
Le stringhe di Rust sono in UTF-8, quindi l'indicizzazione non è disponibile direttamente: s[i] non restituisce il i-esimo carattere e a volte causa panic quando si tenta di accedere a un limite errato di byte. Invece, utilizzare i metodi .chars().nth(i) o .get(start..end).
Si può modificare in modo sicuro &str?
Non si può - &str è sempre uno slice immutabile. Per le modifiche, usare to_owned/to_string, o utilizzare String/Vec<u8>.
Qual è la differenza principale tra String::from("abc") e "abc".to_string()?
Queste opzioni sono equivalenti nel risultato, entrambe creano una String copiando i dati da &str. La differenza sta solo nello stile: ad esempio, to_string è implementato tramite il trait ToString, mentre String::from esprime contrastivamente l'intento di "creare possesso".
La funzione accettava String e faceva una copia non necessaria della stringa all'interno (clone), poi scriveva uno slice in un'altra funzione, dimenticando di estendere la durata della fonte. Risultato: riferimento pendente & crash.
Vantaggi:
Svantaggi:
La funzione accetta &str, se sono necessarie modifiche apre una .to_string(), all'esterno tutta la logica rimane "zero copy". Le durate sono sotto controllo, nessuna allocazione superflua.
Vantaggi:
Svantaggi: