Beginner Fundamentals

Ownership

Ownership is Rust’s core feature for managing memory safely without a garbage collector. The compiler enforces a set of rules at compile time.

The rules

  • Each value has a single owner.
  • There can be only one owner at a time.
  • When the owner goes out of scope, the value is dropped (freed).

Scope and drop

fn main() {
    {
        let s = String::from("hello"); // s owns the string
        println!("{}", s);
    } // s goes out of scope here, memory is freed automatically
}

Move

When you assign one variable to another for a heap value, ownership moves. The original variable can no longer be used.

fn main() {
    let a = String::from("data");
    let b = a; // ownership moves from a to b
    // println!("{}", a); // error: a was moved
    println!("{}", b); // ok
}

Moves into functions

Passing a value to a function also moves it, unless the type is Copy (like integers).

fn consume(s: String) {
    println!("{}", s);
} // s is dropped here

fn main() {
    let text = String::from("hi");
    consume(text);
    // text is no longer usable here
}

Ownership prevents double frees and dangling pointers. To use a value without taking ownership, you borrow it, which is the next lesson.