In this lesson, you will learn how Rust transfers ownership of heap-allocated resources between variables, ensuring that only one owner exists at any given time.
Moving Ownership
In Rust, when you assign a variable that owns data (like a String stored on the heap) to another variable, Rust performs a "move." Instead of copying the actual data on the heap, Rust moves the pointer, length, and capacity from the original variable to the new one.
Critically, once this move occurs, the original variable is considered invalidated. The compiler prevents you from using the old variable again to avoid "double-free" errors, where two variables might both try to clean up the same heap memory when they go out of scope.
A Concrete Example
Consider the following code:
fn main() {
let s1 = String::from("Hello");
let s2 = s1; // The resource is moved here
// println!("{}", s1); // This would cause a compile-time error!
println!("{}", s2); // This is valid
}
In this snippet, s1 holds the heap address of the string "Hello". When we write let s2 = s1;, ownership is transferred to s2. Internally, the stack-based metadata for s1 is wiped. If we attempted to use s1 afterward, the Rust compiler would stop us because s1 no longer "owns" anything. It is as if s1 was never initialized.
This mechanism is central to Rust’s safety. Because only one variable owns the resource, Rust knows exactly when to drop the memory—when that single owner goes out of scope. By invalidating the old owner, Rust forces a clear chain of custody for your data, preventing the ambiguity found in languages where multiple variables might point to the same managed memory.
Key Takeaway: Moving ownership in Rust transfers the responsibility of the data to a new variable and immediately invalidates the previous owner, ensuring memory safety without manual tracking.