Rust Interview Questions

35 Questions
Rust

Rust

Web DevelopmentIoT

Question 4

What is borrowing in Rust, and how does it differ from ownership?

Answer:

In Rust, borrowing is a mechanism that allows you to reference a value without taking ownership of it. This concept is crucial for writing efficient and safe programs, as it enables multiple parts of your code to access data without unnecessarily duplicating it or transferring ownership. Borrowing is different from ownership in several key ways:

Borrowing vs. Ownership:

  1. Ownership:

    • Definition: Ownership means that a variable is responsible for managing the memory of a value. When the owner goes out of scope, the value is dropped (deallocated).
    • Characteristics:
      • Only one variable can own a value at a time.
      • Transferring ownership moves the value from one variable to another, invalidating the original owner.
    • Example:
      fn main() {
          let s1 = String::from("hello");
          let s2 = s1; // s1's ownership is moved to s2.
          // s1 is no longer valid after this point.
          println!("{}", s2);
      }
  2. Borrowing:

    • Definition: Borrowing allows one variable to temporarily access a value owned by another variable without taking ownership. This is done using references.
    • Characteristics:
      • Borrowing can be either immutable (&T) or mutable (&mut T).
      • Multiple immutable borrows are allowed simultaneously, but only one mutable borrow is allowed at a time.
      • Borrowed references must always be valid (i.e., they cannot outlive the owner).
    • Example of Immutable Borrowing:
      fn main() {
          let s = String::from("hello");
          let len = calculate_length(&s); // Borrowing s immutably.
          println!("The length of '{}' is {}", s, len); // s is still valid.
      }
      
      fn calculate_length(s: &String) -> usize {
          s.len()
      }
    • Example of Mutable Borrowing:
      fn main() {
          let mut s = String::from("hello");
          change(&mut s); // Borrowing s mutably.
          println!("{}", s); // s can be used after mutable borrow ends.
      }
      
      fn change(s: &mut String) {
          s.push_str(", world");
      }

Differences between Borrowing and Ownership:

  1. Control and Responsibility:

    • Ownership: The owner has full control and responsibility for the value, including when it gets deallocated.
    • Borrowing: The borrower temporarily gains access to the value without taking control or responsibility for deallocation.
  2. Lifetime:

    • Ownership: The value is valid for as long as the owner is in scope.
    • Borrowing: The borrowed reference is valid only within the scope of the owner and must not outlive it.
  3. Mutability:

    • Ownership: The owner can mutate the value if it is declared mutable.
    • Borrowing: A mutable borrow allows mutation, but an immutable borrow does not. Multiple immutable borrows can coexist, but only one mutable borrow is allowed at a time.
  4. Usage Restrictions:

    • Ownership: Once ownership is transferred, the original owner can no longer use the value.
    • Borrowing: The original owner can continue to use the value if it is immutably borrowed. If it is mutably borrowed, the owner cannot use the value until the borrow ends.

Practical Example Illustrating Borrowing and Ownership:

fn main() {
    let mut s = String::from("hello"); // s owns the String.

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

    // Mutable borrow
    change(&mut s); // s is borrowed 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, calculate_length borrows s immutably, allowing it to read the value without taking ownership. The change function borrows s mutably, 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