Ownership and Borrowing

Ownership

  • No garbage collector. Ownership instead.
  • Each value in Rust has an owner.
  • There can only be one owner at a time.
fn main() {
    let s1 = String::from("hello"); // On the heap
    let _s2 = s1; // s1 was MOVED into s2 - NOT a shallow copy - Rust invalidates s1
    // ERROR println!("{}, world!", s1);
}

When the owner goes out of scope, the value will be dropped.

fn main() {
    {
        let _s = String::from("hello");
    } // variable out of scope - Rust calls `drop`

    // ERROR println!("{}", s);
}

Rust will never automatically create “deep” copies of your data. Use clone

fn main() {
    let s2 = String::from("hello");
    let _s3 = s2.clone();
    // `clone` deeply copies the heap data of the `String`, not just
    // the stack data
}

If a type implements the Copy trait (stack-only, fixed-size values, like integers, floats, and tuples thereof), variables that use it do not move, but rather are trivially copied, making them still valid after assignment to another variable.

fn main() {
    let x = 5; // Integer
    let y = x; // No MOVE

    println!("x = {}, y = {}", x, y); // OK
}

Borrowing

Passing a variable to a function will move or copy, just as assignment does. To avoid passing a value along, borrow the value:

fn main() {
    let s1 = String::from("hello");

    let _len = calculate_length(&s1); // pass an immutable reference to s1

    fn calculate_length(s: &String) -> usize {
        s.len()
    } // Here, s goes out of scope. But because it does not have ownership of what
    // it refers to, s1 is not dropped.
}

Mutable reference

fn change(some_string: &mut String) {
    // note the `&mut`
    some_string.push_str(", world");
}

fn main() {
    let mut s = String::from("hello"); // note the `mut`
    change(&mut s);
}

If you have a mutable reference to a value, you can have no other simultaneous references to that value! Functions like a read/write lock.