Distruzione ["Drop"]

Adesso che abbiamo parlato dei tratti, parliamo di un particolare tratto fornito dalla libreria standard di Rust, Drop, che letteralmente significa "lasciar cadere", ma qui va inteso nel senso di "distruggere". Il tratto Drop svolge la funzione che in altri linguaggi di programmazione è svolta dai "distruttori"; infatti fornisce un modo di eseguire del codice quando un oggetto esce dal suo ambito.

Per esempio:

struct DaDistruggere; impl Drop for DaDistruggere { fn drop(&mut self) { println!("Distruzione!"); } } fn main() { let x = DaDistruggere; // fai qualcosa } // qui x esce di ambito e stampa "Distruzione!"
struct DaDistruggere;

impl Drop for DaDistruggere {
    fn drop(&mut self) {
        println!("Distruzione!");
    }
}

fn main() {
    let x = DaDistruggere;
    
    // fai qualcosa

} // qui x esce di ambito e stampa "Distruzione!"

Quando x esce di ambito, alla fine della funzione main(), il metodo drop verrà eseguito. Tale metodo, che è l'unico di Drop, prende un riferimento mutabile a self.

Ecco fatto! La meccanica di Drop è molto semplice, ma ci sono alcune sottigliezze. Per esempio, i valori vengono distrutti nell'ordine opposto a quello in cui sono stati dichiarati. Ecco un altro esempio:

struct Esplosivo { energia: i32, } impl Drop for Esplosivo { fn drop(&mut self) { println!("BUM per {}!", self.energia); } } fn main() { let petardo = Esplosivo { energia: 1 }; let granata = Esplosivo { energia: 100 }; let bomba = Esplosivo { energia: 1000 }; }
struct Esplosivo {
    energia: i32,
}

impl Drop for Esplosivo {
    fn drop(&mut self) {
        println!("BUM per {}!", self.energia);
    }
}

fn main() {
    let petardo = Esplosivo { energia: 1 };
    let granata = Esplosivo { energia: 100 };
    let bomba = Esplosivo { energia: 1000 };
}

Questo programma stamperà:

BUM per 1000!
BUM per 100!
BUM per 1!

La bomba esplode prima della granata, che esplode prima del petardo, perché sono stati dichiarati in quell'ordine invertito. Ultimo dentro, primo fuori.

Dunque a cosa serve il tratto Drop? In generale, Drop viene usato per distruggere le risorse associate a una struct. Per esempio, Arc<T> è un tipo che contiene un oggetto di tipo generico T e un conteggio di riferimenti. Quando viene chiamato il suo metodo drop, questo metodo decrementa il conteggio dei riferimenti, e se tale conteggio è diventato zero, dealloca l'oggetto contenuto.