Bird
Raised Fist0
Rustprogramming~5 mins

Ownership rules in Rust

Choose your learning style10 modes available
Introduction

Ownership rules help Rust keep track of who owns data to avoid bugs and crashes. They make sure memory is used safely without needing a garbage collector.

When you want to manage memory safely without manual freeing.
When you want to prevent data races in programs with multiple parts using the same data.
When you want to transfer or share data between parts of your program clearly.
When you want to avoid bugs caused by using data after it is deleted.
When you want Rust to help you write fast and safe code.
Syntax
Rust
let s1 = String::from("hello");
let s2 = s1; // ownership moved from s1 to s2
// s1 can no longer be used here

Ownership means one variable is responsible for a piece of data.

When ownership moves, the old owner cannot use the data anymore.

Examples
Here, ownership of the string moves from s1 to s2. Using s1 after is not allowed.
Rust
let s1 = String::from("hello");
let s2 = s1; // s1 loses ownership
// println!("{}", s1); // error: s1 is no longer valid
Using clone() makes a full copy, so both variables own their data independently.
Rust
let s1 = String::from("hello");
let s2 = s1.clone(); // s1 and s2 both own separate copies
println!("{}", s1); // works fine
Passing ownership to a function moves it. After the call, the original variable cannot be used.
Rust
fn take_ownership(s: String) {
    println!("Got: {}", s);
} 
let s = String::from("hello");
take_ownership(s);
// s can no longer be used here
Borrowing with & lets a function use data without taking ownership, so the original variable stays valid.
Rust
fn borrow(s: &String) {
    println!("Borrowed: {}", s);
}
let s = String::from("hello");
borrow(&s);
println!("Still own: {}", s);
Sample Program

This program shows ownership moving from s1 to s2. Then it clones s2 to s3. It also shows borrowing with a reference so ownership is not lost.

Rust
fn main() {
    let s1 = String::from("hello");
    let s2 = s1; // s1 loses ownership
    // println!("{}", s1); // error: s1 is invalid
    println!("s2 owns: {}", s2);

    let s3 = s2.clone(); // s2 and s3 own separate copies
    println!("s2 still owns: {}", s2);
    println!("s3 owns a clone: {}", s3);

    borrow_string(&s3);
    println!("After borrowing, s3 still owns: {}", s3);
}

fn borrow_string(s: &String) {
    println!("Borrowed string: {}", s);
}
OutputSuccess
Important Notes

Ownership rules prevent double freeing memory and dangling pointers.

Only one variable can own data at a time unless you clone it.

Borrowing lets you use data without taking ownership, but you must follow borrowing rules.

Summary

Ownership means one variable is responsible for cleaning up data.

Moving ownership invalidates the old owner.

Borrowing lets you use data temporarily without taking ownership.

Practice

(1/5)
1. What happens when ownership of a variable is moved to another variable in Rust?
easy
A. The original variable becomes invalid and cannot be used.
B. Both variables can be used independently without restrictions.
C. The data is copied and both variables own separate copies.
D. The original variable automatically deletes the data.

Solution

  1. Step 1: Understand ownership move

    When ownership moves, the original variable loses its right to access the data.
  2. Step 2: Effect on original variable

    The original variable becomes invalid and cannot be used to prevent double free errors.
  3. Final Answer:

    The original variable becomes invalid and cannot be used. -> Option A
  4. Quick Check:

    Ownership move invalidates old owner = A [OK]
Hint: Ownership move disables old variable usage [OK]
Common Mistakes:
  • Thinking ownership move copies data
  • Assuming both variables remain valid
  • Confusing move with borrowing
2. Which of the following is the correct syntax to borrow a variable immutably in Rust?
easy
A. let ref x = value;
B. let x = value;
C. let x = *value;
D. let x = &value;

Solution

  1. Step 1: Identify borrowing syntax

    Immutable borrowing uses the & symbol before the variable.
  2. Step 2: Match correct syntax

    let x = &value; correctly borrows value immutably.
  3. Final Answer:

    let x = &value; -> Option D
  4. Quick Check:

    Immutable borrow uses & = B [OK]
Hint: Use & to borrow immutably [OK]
Common Mistakes:
  • Using * for borrowing instead of dereferencing
  • Missing & symbol for borrowing
  • Confusing mutable and immutable borrow syntax
3. What will be the output of this Rust code?
let s1 = String::from("hello");
let s2 = s1;
println!("{}", s1);
medium
A. Runtime error
B. hello
C. Compilation error
D. Empty string

Solution

  1. Step 1: Analyze ownership move

    Assigning s1 to s2 moves ownership, invalidating s1.
  2. Step 2: Using invalidated variable

    Printing s1 after move causes a compile-time error because s1 is no longer valid.
  3. Final Answer:

    Compilation error -> Option C
  4. Quick Check:

    Using moved variable causes compile error = A [OK]
Hint: Using moved variable causes compile error [OK]
Common Mistakes:
  • Expecting s1 to print after move
  • Confusing move with copy
  • Thinking runtime error occurs instead
4. Identify the error in this Rust code snippet:
let s = String::from("hello");
let r1 = &s;
let r2 = &mut s;
println!("{} and {}", r1, r2);
medium
A. No error, code runs fine.
B. Cannot borrow s as mutable because it is already borrowed as immutable.
C. String::from is not a valid function.
D. Cannot print two variables in one println! macro.

Solution

  1. Step 1: Check borrowing rules

    Rust forbids mutable borrow if immutable borrow exists simultaneously.
  2. Step 2: Identify conflict

    r1 is an immutable borrow; r2 tries mutable borrow causing error.
  3. Final Answer:

    Cannot borrow s as mutable because it is already borrowed as immutable. -> Option B
  4. Quick Check:

    Mutable borrow conflicts with existing immutable borrow = D [OK]
Hint: Mutable borrow disallowed if immutable borrow exists [OK]
Common Mistakes:
  • Ignoring borrow rules and expecting code to run
  • Thinking multiple mutable borrows allowed
  • Misunderstanding println! macro usage
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 correct way to fix the error without cloning the string?
hard
A. Change the function parameter to borrow the string: fn take_ownership(s: &String)
B. Remove the println! after the function call.
C. Declare s as mutable in main.
D. Use let s = &String::from("hello"); in main.

Solution

  1. Step 1: Understand ownership transfer

    Passing s to take_ownership moves ownership, invalidating s in main.
  2. Step 2: Use borrowing to avoid move

    Changing parameter to &String borrows s, so ownership stays with main.
  3. Step 3: Adjust function call

    Call take_ownership(&s) to pass reference matching new parameter.
  4. Final Answer:

    Change the function parameter to borrow the string: fn take_ownership(s: &String) -> Option A
  5. Quick Check:

    Borrow parameter to keep ownership in caller = C [OK]
Hint: Borrow in function parameter to keep ownership [OK]
Common Mistakes:
  • Trying to use s after move without borrowing
  • Removing code instead of fixing ownership
  • Confusing mutability with ownership
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