Rust Ownership: Memory Safety Without a Garbage Collector
Rust's ownership model ensures memory safety without a garbage collector. Think of data as having one owner; when the owner goes out of scope, the data is dropped.
WHY IT EXISTS: Traditional languages force a choice between manual memory management (like C++), which is fast but error-prone, and automatic garbage collection (like Go or Java), which is safe but adds runtime overhead. Rust's ownership model was created to provide memory safety guarantees at compile time, eliminating an entire class of bugs without needing a runtime garbage collector.
THE MENTAL MODEL: Think of a value in memory like a physical object with a single, clear owner. You can give that object to someone else, which is a "move". Once you've given it away, it's no longer yours to use. Alternatively, you can lend the object to someone, which is a "borrow". When the owner is finally done with the object (e.g., when the variable goes out of scope), the object is destroyed and its resources are cleaned up.
HOW IT WORKS: The compiler enforces three rules: first, each value has a variable that’s called its owner. Second, there can only be one owner at a time. Third, when the owner goes out of scope, the value is dropped and its memory is freed. When you pass complex data like a String to a function, ownership is "moved". To access data without taking ownership, you "borrow" it. The compiler ensures you can have either one mutable reference OR any number of immutable references, but not both simultaneously, which prevents data races.
WHEN TO USE IT: Ownership is not an optional feature; it's the fundamental principle of writing safe Rust code. It is particularly powerful for building concurrent systems, as the compile-time checks guarantee thread safety without requiring locks in many cases. This makes it ideal for systems programming, embedded devices, and performance-critical services where you need low-level control without sacrificing safety.
WHEN NOT TO USE IT: You can't opt out of ownership, but some data structures are hard to model with a single owner, such as graphs. For these scenarios, Rust provides smart pointers like Rc<T> (Reference Counted) and Arc<T> (Atomic Reference Counted) that allow for shared ownership by tracking the number of references to a value.
ONE CANONICAL EXAMPLE: Consider moving ownership of a string to a function. let s1 = String::from("hello"); takes_ownership(s1); // The next line would cause a compile error because s1's ownership was moved. // println!("s1 is {}", s1);
fn takes_ownership(some_string: String) { println!("Got it: {}", some_string); } // some_string is dropped and its memory freed here.
Read the original → doc.rust-lang.org
Get five bites like this every day.
Tezvyn delivers a daily feed of 60-second tech bites with quizzes to lock in what you learn.