Rust Interview Questions

35 Questions
Rust

Rust

Web DevelopmentIoT

Question 5

What is the difference between &mut and & in Rust?

Answer:

In Rust, &mut and & are used to create mutable and immutable references, respectively. These references allow you to borrow a value without taking ownership, but they come with different capabilities and restrictions.

Immutable References (&)

  • Syntax: &T where T is the type of the value being borrowed.
  • Usage: Allows you to read data without taking ownership or modifying the value.
  • Multiple References: You can have multiple immutable references to the same value simultaneously.
  • Safety: Ensures that the value cannot be modified while it is immutably borrowed, preventing data races.
  • Example:
    fn main() {
        let s = String::from("hello");
        let r1 = &s; // Immutable reference
        let r2 = &s; // Another immutable reference
        println!("{} and {}", r1, r2); // Allowed because both are immutable references
    }

Mutable References (&mut)

  • Syntax: &mut T where T is the type of the value being borrowed.
  • Usage: Allows you to modify the value being borrowed.
  • Single Reference: Only one mutable reference to a value is allowed at a time. This ensures that there are no simultaneous modifications that could lead to data races.
  • Safety: Prevents other references (either mutable or immutable) to the same value while it is mutably borrowed.
  • Example:
    fn main() {
        let mut s = String::from("hello");
        let r = &mut s; // Mutable reference
        r.push_str(", world"); // Allowed because r is a mutable reference
        println!("{}", r);
    }

Key Differences:

  1. Mutability:

    • &: Immutable reference; you can read the value but cannot modify it.
    • &mut: Mutable reference; you can modify the value.
  2. Number of References:

    • &: Multiple immutable references are allowed simultaneously.
    • &mut: Only one mutable reference is allowed at a time. While a mutable reference exists, no immutable references are allowed.
  3. Use Cases:

    • &: Use when you need to read data without modifying it.
    • &mut: Use when you need to modify the data.
  4. Concurrency and Safety:

    • &: Ensures that data cannot be modified, thus preventing data races.
    • &mut: Ensures that only one part of the code can modify the data at a time, also preventing data races.

Practical Example Illustrating Both:

fn main() {
    let mut s = String::from("hello");

    // Immutable borrow
    let len = calculate_length(&s); // Borrowing s immutably
    println!("The length of '{}' is {}", s, len); // s can still be used here

    // Mutable borrow
    change(&mut s); // Borrowing s mutably
    println!("After change: {}", s); // s can be used again after the mutable borrow ends
}

fn calculate_length(s: &String) -> usize {
    s.len() // Access the length without taking ownership
}

fn change(s: &mut String) {
    s.push_str(", world"); // Mutate the String
}

In this example:

  • The calculate_length function borrows s immutably with &s, allowing it to read the value without modifying it.
  • The change function borrows s mutably with &mut s, allowing it to modify the value.
  • After each borrow, s can still be used by the owner since the ownership was never transferred, only temporarily borrowed.

Recent job openings