Rust path · Ownership · Topic 2 of 12

Ownership and moves

Not started

Rust manages memory with three rules the compiler checks: each value has an **owner**; there is only one owner at a time; and when the owner goes out of scope, the value is **dropped**. Dropping runs the type's clean-up code, which for a String or Vec frees its heap buffer. There is no garbage collector looking for unused memory and no free for you to forget or call twice, because the compiler knows statically where each value's life ends.

Why it matters: Ownership is how Rust frees memory without a garbage collector and without manual free calls. Every other rule in the language builds on it, so the compiler errors make sense only once this does.

  1. 1One owner

    Each value is owned by one variable at a time. When the owner goes out of scope the value is dropped, and its heap memory is freed.

  2. 2Assignment moves

    Assigning or passing a String moves ownership; the old variable can't be used any more. Nothing is copied except the small header.

  3. 3Copy types are duplicated

    Integers, floats, bool, char and tuples of them implement Copy, so assignment copies the bits and both stay usable.

  4. 4Clone is explicit

    To get a second independent heap value, call .clone(). The cost is visible in the code.

1

How it works

The explanation, with examples you can run.

Moves

fn shout(s: String) -> String {    s.to_uppercase() // takes ownership of s; s is dropped at the end} fn main() {    let a = String::from("hi");    let b = a; // move: b owns the heap buffer now, a is unusable    // println!("{a}"); // error[E0382]: borrow of moved value: `a`    let c = b.clone(); // deep copy: a second heap buffer    let loud = shout(b); // b moves into the function    println!("{c} {loud}");     let x = 5;    let y = x; // i32 is Copy: both stay usable    println!("{x} {y}");}

It prints hi HI and 5 5. A String is a small struct on the stack (pointer, length, capacity) pointing at bytes on the heap. let b = a copies that struct and makes a invalid, so only one variable will ever free the buffer. Uncomment the println! and the compiler says:

error[E0382]: borrow of moved value: `a`  |2 |     let a = String::from("hi");  |         - move occurs because `a` has type `String`, which does not implement the `Copy` trait3 |     let b = a;  |             - value moved here

Passing a value to a function moves it too, as shout(b) does, and returning a value moves it out to the caller. Moving is cheap: it never copies the heap data.

Copy and Clone

Types whose bits are the whole value, such as integers, floats, bool, char, shared references, and tuples or arrays of them, implement Copy. For them, assignment copies and the original stays usable. A type can be Copy only if it has no Drop code and nothing it owns needs freeing, which is why String isn't.

Clone is the explicit, possibly expensive duplicate. #[derive(Clone)] writes it for your own types. If you see .clone() sprinkled to silence errors, it usually means a borrow would have done.

Drop is deterministic

Values are dropped at the end of the scope that owns them, in reverse order of declaration. Anything can hook into that by implementing Drop: files close, locks unlock and connections return to their pool exactly when their owner goes away, even when a function returns early with ?. This is the same idea as C++'s RAII, enforced by the compiler.

Ownership doesn't mean everything is on the heap. A struct of numbers lives wherever its owner does, often on the stack, and moving it is a plain copy of its bytes. The difference from other languages is that the compiler tracks who is responsible for it.

Passing ownership everywhere would be clumsy, so the next topic, borrowing, lets code use a value without taking it.

2

Check yourself

3 questions. Get them all right to finish this topic.

  1. 1.What happens here?
    let a = String::from("hi");let b = a;println!("{a} {b}");
  2. 2.let x = 5; let y = x; Can x still be used?
  3. 3.When is a String's heap buffer freed?

0 of 3 right so far. Get all three to finish this topic.