Bird
Raised Fist0
Rustprogramming~5 mins

Ownership and functions in Rust - Cheat Sheet & Quick Revision

Choose your learning style10 modes available
Recall & Review
beginner
What happens to ownership when a variable is passed to a function in Rust?
When a variable is passed to a function, ownership is moved to that function unless the type implements the Copy trait or a reference is passed.
Click to reveal answer
beginner
How can you allow a function to use a value without taking ownership in Rust?
You can pass a reference to the value using the & symbol, so the function borrows the value instead of taking ownership.
Click to reveal answer
intermediate
What is the difference between passing a value and passing a reference to a function in Rust?
Passing a value moves ownership to the function, while passing a reference lets the function borrow the value without taking ownership.
Click to reveal answer
intermediate
What happens to the ownership of a value when a function returns it?
The ownership of the returned value moves from the function back to the caller, allowing the caller to use it.
Click to reveal answer
beginner
Why does Rust prevent using a value after its ownership has been moved to a function?
Rust prevents this to avoid bugs like double free or data races by ensuring only one owner exists at a time.
Click to reveal answer
What happens when you pass a String to a function without using a reference?
AOwnership of the String moves to the function.
BThe function borrows the String without ownership.
CThe String is copied to the function.
DThe String is shared between caller and function.
How do you let a function use a value without taking ownership?
APass the value directly.
BPass an immutable reference.
CPass a mutable reference.
DClone the value inside the function.
What must you do to use a value after passing it to a function that takes ownership?
ANothing, you can use it freely.
BUse the value inside the function only.
CPass a reference instead of the value.
DDeclare the variable as mutable.
When a function returns a value, what happens to ownership?
AOwnership is shared.
BOwnership is lost.
COwnership stays inside the function.
DOwnership moves to the caller.
Why does Rust enforce ownership rules with functions?
ATo prevent bugs like double free and data races.
BTo make code run faster.
CTo allow multiple owners of data.
DTo simplify syntax.
Explain how ownership works when passing variables to and returning from functions in Rust.
Think about who owns the data at each step.
You got /3 concepts.
    Describe why Rust uses ownership rules with functions and how it helps prevent bugs.
    Consider what problems ownership solves.
    You got /4 concepts.

      Practice

      (1/5)
      1. What happens when a function in Rust takes ownership of a variable passed to it?
      easy
      A. The variable is shared between the function and the caller simultaneously.
      B. The variable is copied and both original and function have ownership.
      C. The function borrows the variable temporarily without taking ownership.
      D. The original variable can no longer be used after the function call.

      Solution

      1. Step 1: Understand ownership transfer in Rust functions

        When a function takes ownership, it means the variable's ownership moves to the function.
      2. Step 2: Effect on original variable after function call

        Since ownership moved, the original variable cannot be used anymore after the call.
      3. Final Answer:

        The original variable can no longer be used after the function call. -> Option D
      4. Quick Check:

        Ownership transfer = original variable unusable [OK]
      Hint: Ownership moves to function, original variable becomes invalid [OK]
      Common Mistakes:
      • Thinking ownership is shared, not moved
      • Assuming variable is copied automatically
      • Confusing borrowing with ownership transfer
      2. Which of the following function signatures correctly borrows a string slice without taking ownership?
      easy
      A. fn print_name(name: String) { println!("{}", name); }
      B. fn print_name(name: &String) { println!("{}", name); }
      C. fn print_name(name: &str) { println!("{}", name); }
      D. fn print_name(name: String) -> String { name }

      Solution

      1. Step 1: Identify borrowing syntax for string slices

        Borrowing a string slice uses &str type, which is a reference to a string slice.
      2. Step 2: Check each signature for borrowing without ownership

        fn print_name(name: &str) { println!("{}", name); } uses &str, which borrows without taking ownership. fn print_name(name: &String) { println!("{}", name); } borrows a String reference but &str is more idiomatic for slices.
      3. Final Answer:

        fn print_name(name: &str) { println!("{}", name); } -> Option C
      4. Quick Check:

        Borrow string slice = &str parameter [OK]
      Hint: Use &str to borrow string slices without ownership [OK]
      Common Mistakes:
      • Using String parameter takes ownership
      • Confusing &String with &str
      • Returning ownership when not needed
      3. What will be the output of this Rust code?
      fn take_ownership(s: String) {
          println!("Inside function: {}", s);
      }
      
      fn main() {
          let s = String::from("hello");
          take_ownership(s);
          println!("Outside function: {}", s);
      }
      medium
      A. Inside function: hello Compile error: use of moved value 's'
      B. Inside function: hello Outside function: hello
      C. Inside function: hello Outside function: <empty>
      D. Runtime error: variable s not found

      Solution

      1. Step 1: Analyze ownership transfer in function call

        The function take_ownership takes ownership of s, so s is moved into the function.
      2. Step 2: Check usage of s after function call

        After the call, s is no longer valid in main, so using it causes a compile error.
      3. Final Answer:

        Inside function: hello Compile error: use of moved value 's' -> Option A
      4. Quick Check:

        Ownership moved, use after move = compile error [OK]
      Hint: Using moved variable after function call causes compile error [OK]
      Common Mistakes:
      • Assuming variable is copied automatically
      • Expecting output after ownership moved
      • Ignoring Rust's ownership rules
      4. Identify the error in this Rust code and how to fix it:
      fn calculate_length(s: String) -> usize {
          s.len()
      }
      
      fn main() {
          let s1 = String::from("hello");
          let len = calculate_length(s1);
          println!("The length of '{}' is {}.", s1, len);
      }
      medium
      A. Error: s1 is moved into calculate_length; fix by passing &s1 instead.
      B. Error: calculate_length returns wrong type; fix by returning &usize.
      C. Error: println! macro syntax incorrect; fix by removing quotes.
      D. No error; code runs and prints length correctly.

      Solution

      1. Step 1: Identify ownership issue in function call

        calculate_length takes ownership of s1, so s1 is moved and invalid after call.
      2. Step 2: Fix by borrowing s1 instead of moving

        Change function parameter to &String and pass &s1 to avoid moving ownership.
      3. Final Answer:

        Error: s1 is moved into calculate_length; fix by passing &s1 instead. -> Option A
      4. Quick Check:

        Pass reference to avoid moving ownership [OK]
      Hint: Pass references to keep ownership when calling functions [OK]
      Common Mistakes:
      • Trying to return reference to local variable
      • Ignoring ownership move on function parameters
      • Misunderstanding borrowing syntax
      5. You want to write a function that takes ownership of a vector, doubles each element, and returns ownership back. Which function signature and body correctly implement this in Rust?
      hard
      A. fn double_vec(v: &Vec<i32>) -> Vec<i32> { v.iter().map(|x| x * 2).collect() }
      B. fn double_vec(v: Vec<i32>) -> Vec<i32> { v.iter().map(|x| x * 2).collect() }
      C. fn double_vec(v: Vec<i32>) { for x in &v { println!("{}", x * 2); } }
      D. fn double_vec(v: &mut Vec<i32>) { for x in v { *x *= 2; } }

      Solution

      1. Step 1: Understand ownership and return requirements

        The function must take ownership of the vector and return ownership back after doubling elements.
      2. Step 2: Analyze each option for ownership and functionality

        fn double_vec(v: Vec<i32>) -> Vec<i32> { v.iter().map(|x| x * 2).collect() } takes ownership (Vec<i32>), creates a new doubled vector, and returns it, satisfying requirements.
      3. Final Answer:

        fn double_vec(v: Vec<i32>) -> Vec<i32> { v.iter().map(|x| x * 2).collect() } -> Option B
      4. Quick Check:

        Take ownership, return new doubled vector [OK]
      Hint: Take Vec ownership and return new Vec after processing [OK]
      Common Mistakes:
      • Borrowing vector but not returning ownership
      • Not returning anything from function
      • Modifying borrowed vector without 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