MST
星途 面试题库

面试题:Rust引用在所有权系统中的角色

在Rust的所有权系统下,引用(包括不可变引用和可变引用)是如何与所有权相互配合工作的?如果在一段代码中违反了引用的规则,会出现什么编译错误,应该如何修改?请结合具体代码示例说明。
17.1万 热度难度
编程语言Rust

知识考点

AI 面试

面试题答案

一键面试
  1. 引用与所有权的配合
    • 不可变引用
      • 在Rust中,所有权规则确保同一时刻只能有一个所有者。不可变引用允许我们在不获取所有权的情况下访问数据,并且可以有多个不可变引用同时存在。这有助于在需要读取数据时避免数据竞争。例如:
fn main() {
    let s = String::from("hello");
    let r1 = &s;
    let r2 = &s;
    println!("{} and {}", r1, r2);
}
 - 在这段代码中,`s`拥有字符串的所有权,`r1`和`r2`是对`s`的不可变引用。多个不可变引用可以同时存在,因为它们只读取数据,不会修改数据,所以不会产生数据竞争。
  • 可变引用
    • 可变引用允许我们修改数据,但为了避免数据竞争,同一时刻只能有一个可变引用存在,并且在有可变引用时不能有不可变引用。例如:
fn main() {
    let mut s = String::from("hello");
    let r1 = &mut s;
    r1.push_str(", world");
    println!("{}", r1);
}
 - 这里`mut s`表明`s`是可变的,`r1`是对`s`的可变引用。通过`r1`可以修改`s`所指向的字符串。如果试图在有可变引用`r1`的同时创建不可变引用,会导致编译错误。

2. 违反引用规则的编译错误及修改

  • 错误示例1:同时存在可变和不可变引用
fn main() {
    let mut s = String::from("hello");
    let r1 = &s;
    let r2 = &mut s;
    println!("{} and {}", r1, r2);
}
 - 编译时会报错,类似`error[E0502]: cannot borrow `s` as mutable because it is also borrowed as immutable`。原因是同时存在对`s`的不可变引用`r1`和可变引用`r2`,违反了Rust的引用规则。
 - **修改方法**:确保在创建可变引用之前,不可变引用不再使用。例如:
fn main() {
    let mut s = String::from("hello");
    let r1 = &s;
    println!("{}", r1);
    let r2 = &mut s;
    r2.push_str(", world");
    println!("{}", r2);
}
  • 错误示例2:多个可变引用
fn main() {
    let mut s = String::from("hello");
    let r1 = &mut s;
    let r2 = &mut s;
    r1.push_str(", world");
    r2.push_str("!");
}
 - 编译时会报错,类似`error[E0499]: cannot borrow `s` as mutable more than once at a time`。因为同一时刻有多个可变引用`r1`和`r2`指向`s`。
 - **修改方法**:确保同一时刻只有一个可变引用。例如:
fn main() {
    let mut s = String::from("hello");
    let r1 = &mut s;
    r1.push_str(", world");
    let r2 = &mut s;
    r2.push_str("!");
}

这样修改后,r1使用完后再创建r2,就不会违反引用规则。