Vai al contenuto
eLearner.app
Modulo 6 · Lezione 1 di 211/14 nel corso~15 min
Lezioni del modulo (1/2)

Lifetimes e riferimenti

In Rust, ogni riferimento ha un lifetime (durata), che corrisponde all'ambito (scope) all'interno del quale quel riferimento è valido. La maggior parte delle volte i lifetime sono impliciti e dedotti dal compilatore grazie alle regole di elisione. Tuttavia, quando la relazione tra i lifetime di diversi riferimenti è ambigua, dobbiamo annotarli esplicitamente.

L'obiettivo principale dei lifetime è prevenire i dangling references (riferimenti a dati che sono già stati deallocati dalla memoria).


La Sintassi delle Annotazioni dei Lifetime

I nomi dei lifetime iniziano con un apostrofo (') e sono solitamente scritti in lettere minuscole molto brevi (come 'a). Le annotazioni dei lifetime non cambiano la durata effettiva delle variabili, ma indicano al compilatore la relazione di validità tra i riferimenti ricevuti ed eventualmente restituiti.

Ad esempio, se una funzione prende due parametri che sono riferimenti a stringa e restituisce un riferimento a stringa, e vogliamo che il riferimento restituito sia valido finché entrambi i parametri in input sono validi, usiamo:

Code
fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
    if x.len() > y.len() {
        x
    } else {
        y
    }
}

Lifetime nelle Strutture dati

Se una struttura dati contiene un campo che è un riferimento, dobbiamo annotare esplicitamente il lifetime su quel riferimento per garantire che l'istanza della struct non possa sopravvivere al dato a cui si riferisce:

Code
struct ImportantExcerpt<'a> {
    part: &'a str,
}

fn main() {
    let novel = String::from("Chiamami Ismaele. Alcuni anni fa...");
    let first_sentence = novel.split('.').next().unwrap();
    let i = ImportantExcerpt {
        part: first_sentence,
    };
}

Il Lifetime Statico

Il lifetime 'static è un lifetime speciale che dura per l'intera durata dell'esecuzione del programma. Tutti i letterali stringa (&str) hanno implicitamente un lifetime 'static perché sono codificati direttamente all'interno dell'eseguibile binario.

Code
let s: &'static str = "Ho un lifetime statico.";

Prova tu

Esercizio 1: La funzione longest

Esercizio#rust.m6.l1.e1
Tentativi: 0Caricamento…

Scrivi una funzione chiamata longest<'a> che accetta due parametri, x di tipo &'a str e y di tipo &'a str, e restituisce un valore di tipo &'a str. All'interno della funzione, usa un costrutto if/else per restituire il parametro x se la sua lunghezza è maggiore di y, altrimenti restituisci y.

Caricamento editor…
Mostra suggerimento

Dichiara la firma con `fn longest<'a>(x: &'a str, y: &'a str) -> &'a str`. Poi usa `if x.len() > y.len() { x } else { y }`.

Soluzione disponibile dopo 3 tentativi

Esercizio 2: Strutture con riferimenti

Esercizio#rust.m6.l1.e2
Tentativi: 0Caricamento…

Definisci una struttura chiamata Excerpt<'a> contenente un singolo campo chiamato part di tipo &'a str. Nel main, crea una variabile stringa chiamata text ed istanzia una variabile excerpt di tipo Excerpt prestando un riferimento a text. Stampa a schermo excerpt.part.

Caricamento editor…
Mostra suggerimento

Usa `struct Excerpt<'a> { part: &'a str }`. Nel main istanziala con `Excerpt { part: &text }`.

Soluzione disponibile dopo 3 tentativi

Esercizio 3: Riferimenti statici

Esercizio#rust.m6.l1.e3
Tentativi: 0Caricamento…

Dichiara una variabile chiamata message con annotazione di tipo esplicita per il lifetime statico (&'static str), assegnandole un valore letterale stringa. Stampa a schermo il valore di message.

Caricamento editor…
Mostra suggerimento

Usa la sintassi `let message: &'static str = 'Messaggio statico!';` per annotare esplicitamente il lifetime statico.

Soluzione disponibile dopo 3 tentativi