← Back to Rust Course | Chapter 5: Ownership | Lesson 2 of 6

Move Semantics

When you hand a value to someone else in Rust, you can't use your old copy of it anymore -- it really moved.

Moving Ownership on Assignment

When you assign a String (or other heap-allocated, non-Copy type) to a new variable, Rust moves the underlying data's ownership rather than copying it, and invalidates the original variable.

Example: Moving Ownership on Assignment

markup
fn main() {
    let original = String::from("Rustacean");
    let moved = original;
    println!("moved holds: {}", moved);
}

Moves Happen on Function Calls Too

Passing a non-Copy value into a function moves ownership into that function's parameter. After the call, the caller's variable is no longer valid unless the value is returned back.

Example: Moves Happen on Function Calls Too

markup
fn take_ownership(s: String) {
    println!("Function now owns: {}", s);
}

fn main() {
    let text = String::from("hello");
    take_ownership(text);
    println!("text was moved into the function");
}

Getting a Value Back by Returning It

A function can return ownership of a value back to the caller, letting you keep using it under a (possibly new) variable name after the call.

Example: Getting a Value Back by Returning It

markup
fn process(s: String) -> String {
    println!("Processing: {}", s);
    s
}

fn main() {
    let text = String::from("data");
    let text = process(text);
    println!("Back in main: {}", text);
}

Why Rust Uses Moves Instead of Deep Copies

Copying large heap-allocated data every time it is assigned would be slow. Moves let Rust transfer ownership cheaply (just copying a pointer, length, and capacity) while the compiler guarantees only one owner uses that memory.

Example: Why Rust Uses Moves Instead of Deep Copies

markup
fn main() {
    let large_data = vec![1; 5];
    let transferred = large_data;
    println!("Transferred without deep copy: {:?}", transferred);
}
Common Mistakes
  1. Trying to use a variable after moving its value into another variable or into a function, causing a compile error.
  2. Assuming assignment always copies data like it might in some other languages -- for heap types, assignment moves by default.
  3. Confusing a move with a shallow copy that leaves two usable references to the same data -- Rust invalidates the original.
Chapter Summary
  • Assigning a non-Copy value to another variable moves ownership; the original variable becomes invalid.
  • Passing a non-Copy value into a function also moves it, unless the function takes a reference.
  • Using a moved-from variable is a compile-time error, not a runtime bug.
  • Move semantics avoid the cost of deep-copying data while still preventing use-after-free.
🔒

Chapter Quiz — Complete all 6 topics to unlock

0/6 topics done

Complete these topics first:

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.