为何允许将Rust可变引用转为不可变引用且不违反借用规则?
Rust引用规则的疑问
来自Rust官方书籍:
在任意给定时间,你只能拥有一个可变引用,或任意数量的不可变引用。
考虑以下代码:
fn main() { let mut a = 41; let b = &mut a; let c: &i32 = &a; // [1] let d: &i32 = &b; println!("{} {}", b, c); // [2] println!("{} {}", b, d); }
尝试编译时会得到如下错误:
error[E0502]: cannot borrow `a` as immutable because it is also borrowed as mutable --> src\main.rs:43:19 | 42 | let b = &mut a; | ------ mutable borrow occurs here 43 | let c: &i32 = &a; // [1] | ^^ immutable borrow occurs here 44 | let d: &i32 = &b; | -- mutable borrow later used here
这符合“只能拥有一个可变引用”的规则。但如果注释掉标记为[1]和[2]的行,代码就能正常编译。此时b是可变引用,d是不可变引用(看似与c情况相同)。
请问为何允许这种场景存在?为何该情况编译通过却不违反“同一时间只能有一个可变引用或多个不可变引用”的规则?
这本质是直接引用原变量和引用“引用”本身的区别,核心看Rust借用检查器追踪的是对原变量a的借用关系:
- 写
let c = &a时,是直接对原变量a创建新的不可变引用,此时a已经被b以可变方式借用,直接触发“可变/不可变引用不能共存”的规则,所以报错。 - 而
let d = &b的情况,你并没有直接借用a,而是借用了可变引用b这个变量本身:d的实际类型是&&mut i32,自动解引用后表现为&i32,但它本质是指向b的不可变引用,不是指向a的。- 对原变量
a来说,始终只有b这一个可变引用;d只是“挂靠”在b上,没有触碰a的直接借用权限,完全不违反引用规则。
简单说:c是直接抢着借a,和b的借用冲突;d是借b这个“中间人”,没碰a的借用权限,所以合法。
内容的提问来源于stack exchange,提问作者Eugene Loy
相关产品推荐
相关产品推荐

