Rust引用相关问题:引用何时超出作用域?为何出现两次可变借用?
Rust引用作用域与可变借用问题解答
1. 引用何时会超出作用域?
- 引用的作用域分两种场景:
- 词法作用域:如果引用在代码块(如
{})内创建,代码块执行结束时,引用立即失效。 - 非词法作用域(NLL):Rust编译器会追踪引用的最后一次使用位置,从引用创建到该位置的区间就是有效作用域,之后引用自动释放,不再占用借用权限。
- 词法作用域:如果引用在代码块(如
- 注意:变量本身的作用域和引用的作用域是两回事,变量的作用域从声明到词法作用域结束,但引用的作用域可能更早结束,只要它不再被使用。
2. 代码示例中的两次可变借用错误原因分析
问题代码如下:
fn main() { let mut my_string = String::from("this is a string"); let mut other_string_ref = &mut my_string; // first mutable reference mut_ref(&mut my_string); mut_ref(&mut other_string_ref); // invalid, because borrowed twice } // borrow happens when this function is called fn mut_ref(s: &mut String) { print!("{}\n", s) }
错误核心逻辑:
- 执行
let mut other_string_ref = &mut my_string;时,创建了对my_string的可变引用other_string_ref,它的有效作用域会延续到最后一次使用它的位置——也就是第二个mut_ref调用处。 - 第一个
mut_ref(&mut my_string);调用时,又直接对my_string创建了临时可变引用并传入函数。此时other_string_ref的作用域尚未结束(后续还要使用),导致同一时间存在两个对my_string的可变引用,违反了Rust的借用规则(同一时间只能有一个可变引用,避免数据竞争)。
针对你提到的“为何执行mut_ref(&mut my_string);后,my_string并未超出作用域”:
my_string作为变量的作用域覆盖整个main函数,不会因为一次函数调用就结束。- 更关键的是,
other_string_ref是对my_string的可变引用,只要other_string_ref还在有效作用域内(未到最后一次使用),my_string的可变借用权限就被它占用,无法被其他可变引用借用。哪怕后续没直接使用my_string,使用other_string_ref等同于仍在占用my_string的可变借用权限。
如果要修复错误,可以调整引用使用顺序,让第一个可变引用的作用域提前结束:
fn main() { let mut my_string = String::from("this is a string"); { let mut other_string_ref = &mut my_string; mut_ref(&mut other_string_ref); // 先使用该引用 } // 代码块结束,other_string_ref作用域失效 mut_ref(&mut my_string); // 可重新借用my_string } fn mut_ref(s: &mut String) { print!("{}\n", s) }
或者利用非词法作用域,确保other_string_ref在第一次借用my_string前完成最后一次使用:
fn main() { let mut my_string = String::from("this is a string"); let mut other_string_ref = &mut my_string; mut_ref(&mut other_string_ref); // 这是other_string_ref的最后一次使用 mut_ref(&mut my_string); // 此时other_string_ref作用域已结束,可安全借用 } fn mut_ref(s: &mut String) { print!("{}\n", s) }
内容的提问来源于stack exchange,提问作者User12547645
相关产品推荐
相关产品推荐

