RS Rust

Rust: Ownership & Borrowing

What you will learn

Rust's most unique feature: the ownership system that guarantees memory safety without a garbage collector.

Ownership rules (memorize these)

  1. Each value in Rust has exactly one owner.
  2. When the owner goes out of scope, the value is dropped (freed).
  3. You can borrow a reference without taking ownership.

Move semantics

let s1 = String::from("hello");
let s2 = s1;  // ownership MOVES from s1 to s2
// println!("{}", s1);  // compile error -- value moved

When s1 is assigned to s2, the String data does not get copied. Instead, the ownership moves. s1 is no longer valid -- Rust prevents use-after-move at compile time.

Clone (deep copy)

If you want a deep copy instead of a move:

let s1 = String::from("hello");
let s2 = s1.clone();  // deep copy
println!("{}, {}", s1, s2);  // both valid

Borrowing with references

A reference (&) lets you use a value without taking ownership:

fn calc_len(s: &String) -> usize {
    s.len()
}  // s goes out of scope, but it was only borrowed -- s1 keeps ownership

let s1 = String::from("hello");
let len = calc_len(&s1);
println!("{}", s1);  // still valid because we only borrowed

Mutable references

To modify a borrowed value, use &mut:

fn change(s: &mut String) {
    s.push_str(" world");
}

let mut s = String::from("hello");
change(&mut s);
println!("{}", s);  // "hello world"

Important rule: you can have either one mutable reference or any number of immutable references, but never both at the same time.

Common mistakes

  • Trying to use a variable after a move -- Rust is strict about this. Clone if you need both.
  • Creating two mutable references to the same data -- Rust rejects this at compile time to prevent data races.
  • Thinking = always copies -- it only copies for simple types like integers (which implement Copy). Strings and most other types move.

Quick check below!