Destructors - Drop

Rust doesn't explicitly define destructors---there's no need to define a destructor in most cases. So you won't encounter ~MyClass() functions.

That doesn't mean that Rust has abandoned RAII---Resource Acquisition is Initialiation. Rather, Rust has adopted it wholesale and associated destructors with a trait called Drop.

Drop is implemented for all of the container types, smart pointers, etc. Whenever a variable leaves scope, the Drop trait is called prior to a type being deleted. Let's explicitly implement Drop to demonstrate this:

struct MyStruct {}

impl Drop for MyStruct {
    fn drop(&mut self) {
        println!("I was dropped");
    }
}

fn main() {
    let a= MyStruct{};
}

Not too surprisingly---the drop function runs at the end of the program. This applies to local variables in a function, too:

struct MyStruct {}

impl Drop for MyStruct {
    fn drop(&mut self) {
        println!("I was dropped");
    }
}

fn do_something() {
    let a = MyStruct{};
}

fn main() {
    println!("Calling function");
    do_something();
    println!("Returned");
}

Dropping works on variables held by a structure even if the structure doesn't itself explicitly implement Drop:

struct MyContainer { data: Vec<MyStruct> }

struct MyStruct {}

impl Drop for MyStruct {
    fn drop(&mut self) {
        println!("I was dropped");
    }
}

fn main() {
    let mc = MyContainer {
        data: vec![MyStruct{}, MyStruct{}, MyStruct{}]
    };
}

So---just like C++---RAII makes it very difficult to accidentally leak memory. We'll go over this in a lot more detail soon.

You can also explicitly drop anything:

struct MyContainer { data: Vec<MyStruct> }

struct MyStruct {}

impl Drop for MyStruct {
    fn drop(&mut self) {
        println!("I was dropped");
    }
}

fn main() {
    let mc = MyContainer {
        data: vec![MyStruct{}, MyStruct{}, MyStruct{}]
    };
    std::mem::drop(mc);
    // Accessing mc is now a compilation error
}