编程后端开发者

描述Rust中不同类型的引用:可变引用和不可变引用之间的区别、独占性和生命周期规则,以及如何正确编写接受不同类型引用的函数。提供语法示例并讨论引用相关的典型错误。

用 Hintsage AI 助手通过面试

答案

在Rust中有两种主要的引用类型:

  • 不可变引用 (&T):仅提供读取访问。
  • 可变引用 (&mut T):允许更改所引用的值。

规则:

  • 在同一作用域中可以有任意数量的不可变引用,或者仅有一个可变引用;不可混合使用。
  • 引用具有生命周期(lifetime),在编译阶段进行分析。

语法示例:

fn read(val: &i32) { println!("{}", val); } fn write(val: &mut i32) { *val += 1; } let mut x = 5; read(&x); write(&mut x);

令人困惑的问题

问题: 是否可以在同一函数的不同作用域中为一个变量创建两个可变引用?

答案: 不可以,即使引用是在不同的块中创建,借用分析的作用域会覆盖整个函数或变量,如果编译器无法明确证明引用不会交叉。这通常导致编译错误:

let mut x = 10; let r1 = &mut x; { let r2 = &mut x; // 错误! }

由于对主题细节的无知而导致的实际错误示例


故事

在解析器开发中,开发人员试图同时存储一个缓冲区的可变引用和不可变引用以优化读取和写入。结果是代码无法编译,并且在通过不安全代码“绕过”规则后出现数据泄漏的错误。


故事

在数据处理项目启动时,参与者没有对复杂代码的嵌套作用域执行“重新分析借用检查器”。因此,由于交叉引用出现了经典的“无法借用为可变,因为它也被不可变借用”的错误,而在源代码中没有明确指出问题所在。


故事

在多线程代码中,使用普通引用来访问共享数据。尝试在并行线程中修改数据时,会遇到意想不到的编译错误和通过不安全代码绕过借用检查器时出现的数据竞争。