Bird
Raised Fist0
Rustprogramming~10 mins

Move semantics in Rust - Step-by-Step Execution

Choose your learning style10 modes available
Concept Flow - Move semantics
Create variable with data
↓
Assign variable to new owner
↓
Original variable becomes invalid
↓
Use new owner variable
↓
Original variable cannot be used anymore
Move semantics transfers ownership of data from one variable to another, invalidating the original variable.
Execution Sample
Rust
let s1 = String::from("hello");
let s2 = s1;
println!("{}", s2);
This code moves ownership of the string from s1 to s2, making s1 invalid.
Execution Table
StepActionVariableValueOwnership StatusNotes
1Create s1s1"hello"Owners1 owns the string data
2Move s1 to s2s1InvalidNot owners1 is invalid after move
2Move s1 to s2s2"hello"Owners2 now owns the string data
3Print s2s2"hello"Owners2 can be used to access data
4Attempt to use s1s1InvalidNot ownerUsing s1 causes compile error
💡 Execution stops because s1 is invalid after move; only s2 owns the data.
Variable Tracker
VariableStartAfter MoveFinal
s1"hello"InvalidInvalid
s2N/A"hello""hello"
Key Moments - 3 Insights
Why can't we use s1 after assigning it to s2?
Because ownership of the data moves from s1 to s2 at step 2, s1 becomes invalid and cannot be used (see execution_table row 2).
Does the data get copied when we assign s1 to s2?
No, the data is moved, not copied. The ownership transfers to s2, and s1 loses access (execution_table rows 2).
What happens if we try to print s1 after the move?
The compiler will give an error because s1 is invalid after the move (execution_table row 4).
Visual Quiz - 3 Questions
Test your understanding
Look at the execution table, what is the ownership status of s1 after step 2?
ANot owner
BOwner
CStill valid
DCopied
💡 Hint
Check the 'Ownership Status' column for s1 at step 2 in the execution_table.
At which step does s2 become the owner of the string data?
AStep 1
BStep 2
CStep 3
DStep 4
💡 Hint
Look at the 'Variable' and 'Ownership Status' columns for s2 in the execution_table.
If we tried to use s1 after step 2, what would happen?
AIt would print the string
BIt would print an empty string
CIt would cause a compile error
DIt would copy the data back
💡 Hint
See the note in execution_table row 4 about using s1 after move.
Concept Snapshot
Move semantics in Rust:
- Ownership transfers from one variable to another.
- Original variable becomes invalid after move.
- No data copying occurs during move.
- Using moved-from variable causes compile error.
- Ensures memory safety without garbage collection.
Full Transcript
This example shows move semantics in Rust. First, a string is created and owned by variable s1. When s1 is assigned to s2, ownership moves to s2 and s1 becomes invalid. After the move, s2 can be used to access the string, but s1 cannot. Trying to use s1 after the move causes a compile error. This behavior prevents double frees and ensures safe memory management.

Practice

(1/5)
1. What happens to a variable in Rust after its value is moved to another variable?
easy
A. The original variable can no longer be used.
B. The original variable keeps a copy of the value.
C. The original variable is automatically cloned.
D. The original variable becomes a reference to the new variable.

Solution

  1. Step 1: Understand move semantics

    In Rust, moving a value transfers ownership from one variable to another.
  2. Step 2: Effect on original variable

    After the move, the original variable is invalid and cannot be used to prevent double free errors.
  3. Final Answer:

    The original variable can no longer be used. -> Option A
  4. Quick Check:

    Move means original variable unusable [OK]
Hint: Moving means original variable is invalid after transfer [OK]
Common Mistakes:
  • Thinking the original variable still holds a copy
  • Assuming Rust automatically clones on move
  • Confusing move with borrowing
2. Which of the following Rust code snippets correctly moves ownership of a String from a to b?
easy
A. let b = a.clone();
B. let b = &a;
C. let b = a;
D. let b = *a;

Solution

  1. Step 1: Identify move syntax

    Assigning let b = a; moves ownership of a to b.
  2. Step 2: Check other options

    &a borrows, a.clone() copies, *a is invalid for String.
  3. Final Answer:

    let b = a; -> Option C
  4. Quick Check:

    Simple assignment moves ownership [OK]
Hint: Use simple assignment to move ownership, not references or clone [OK]
Common Mistakes:
  • Using references instead of moving
  • Using clone which copies instead of moves
  • Dereferencing a String which is invalid
3. What is the output of this Rust code?
let s1 = String::from("hello");
let s2 = s1;
println!("{}", s1);
medium
A. Compilation error
B. hello
C. Runtime error
D. Empty string

Solution

  1. Step 1: Analyze ownership transfer

    Assigning s2 = s1 moves ownership of the String from s1 to s2.
  2. Step 2: Using moved variable

    Trying to print s1 after move causes a compile-time error because s1 is invalid.
  3. Final Answer:

    Compilation error -> Option A
  4. Quick Check:

    Using moved variable causes compile error [OK]
Hint: Using moved variable causes compile error, not runtime [OK]
Common Mistakes:
  • Expecting output 'hello' despite move
  • Thinking it causes runtime error
  • Assuming Rust clones automatically
4. Identify the error in this Rust code related to move semantics:
fn main() {
    let v = vec![1, 2, 3];
    let v2 = v;
    println!("{}", v.len());
}
medium
A. Vector v cannot be moved to v2.
B. Cannot print vector length with println!.
C. Missing semicolon after let v2 = v.
D. Using v.len() after v was moved to v2.

Solution

  1. Step 1: Understand move of vector

    Assigning v2 = v moves ownership of vector v to v2.
  2. Step 2: Using moved variable causes error

    Calling v.len() after move is invalid and causes compile error.
  3. Final Answer:

    Using v.len() after v was moved to v2. -> Option D
  4. Quick Check:

    Using moved variable causes compile error [OK]
Hint: After move, original variable cannot be used [OK]
Common Mistakes:
  • Thinking vector cannot be moved
  • Ignoring ownership rules after move
  • Confusing move with borrowing
5. Given this Rust function:
fn take_ownership(s: String) {
    println!("{}", s);
}

fn main() {
    let s = String::from("hello");
    take_ownership(s);
    println!("{}", s);
}

What is the best way to fix the code so main can print s after calling take_ownership?
hard
A. Clone s before passing: take_ownership(s.clone()).
B. All of the above.
C. Return s from take_ownership and assign it back.
D. Change take_ownership to take a reference: fn take_ownership(s: &String).

Solution

  1. Step 1: Understand ownership transfer in function

    Passing s to take_ownership moves ownership, invalidating s in main.
  2. Step 2: Ways to keep s usable

    Change take_ownership to take a reference: fn take_ownership(s: &String). borrows s so ownership is not moved.
    Clone s before passing: take_ownership(s.clone()). clones s so original remains.
    Return s from take_ownership and assign it back. returns ownership back to main.
  3. Step 3: Best fix

    All three options correctly fix the problem.
  4. Final Answer:

    All of the above. -> Option B
  5. Quick Check:

    Borrow, clone, or return ownership fixes [OK]
Hint: Borrow, clone, or return ownership to keep variable usable [OK]
Common Mistakes:
  • Ignoring ownership transfer in function calls
  • Not cloning when needed
  • Not returning ownership back
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard