Understanding Ownership in Rust
Feb 15, 2025 7 min
What is Ownership?
Every value in Rust has a single owner. When the owner goes out of scope, the value is dropped.
{
let s = String::from("hello");
// s is valid here
} // s goes out of scope → memory freed
The Rules
- Each value has exactly one owner
- There can be at most one mutable reference
- References must always be valid
Moving vs Copying
// Move: ownership transfers
let s1 = String::from("hello");
let s2 = s1;
// println!("{s1}"); // Error! s1 is moved
// Copy: stack-only data is copied
let x = 5;
let y = x;
println!("{x}"); // OK, integers implement Copy
Borrowing
References let you use a value without taking ownership:
fn calculate_len(s: &String) -> usize {
s.len()
} // s is not dropped here
let s = String::from("hello");
let len = calculate_len(&s);
println!("{s}"); // OK
Mutable References
fn change(s: &mut String) {
s.push_str(" world");
}
let mut s = String::from("hello");
change(&mut s);
A key rule: you can have either one mutable reference or any number of immutable references.
Lifetimes
Lifetimes ensure references are always valid:
fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
if x.len() > y.len() { x } else { y }
}
The 'a annotation means “the returned reference lives as long as both inputs.”
Summary
Ownership might feel restrictive at first, but the compiler’s strictness prevents entire categories of bugs. Once it clicks, you’ll appreciate the safety guarantees.