关于Rust可变引用作用域规则与代码编译结果不符的疑问
Rust可变引用规则的疑问:为何这段代码能编译通过?
问题背景
我正在学习Rust中的引用,《Programming Rust》里提到:
只要存在值的共享引用,即使其所有者也无法修改该值;若存在值的可变引用,它拥有对该值的独占访问权,在可变引用失效前,所有者完全无法使用该值。
但我写的这段代码却能正常编译:
let mut a = vec![1, 2, 3]; let b = &mut a; b.push(5); a.push(4);
按照书中描述,可变引用b仍在作用域内时,a.push()应该编译失败,想纠正我的错误认知。
解答:Rust的非词法生命周期(NLL)
你之前的认知是基于词法作用域的旧规则,但Rust 1.31版本引入了非词法生命周期(Non-Lexical Lifetimes, NLL),编译器会智能分析引用的最后一次使用位置,而不是简单以代码块的作用域作为引用失效的边界。
在你的代码里,b的最后一次使用是b.push(5);这一行,执行完这行后,b就再也没有被用到了。编译器会判定b的生命周期在这里就结束了,所以之后对a的访问(a.push(4);)不会和b的可变引用产生冲突,因此可以正常编译。
如果调整代码顺序,让b的使用在a.push()之后:
let mut a = vec![1, 2, 3]; let b = &mut a; a.push(4); // 这里会编译错误 b.push(5);
此时编译器就会报错,因为b的最后一次使用在a.push()之后,a的访问和b的独占可变引用产生了冲突,符合你最初理解的规则。
简单来说,NLL让编译器更精准地判断引用的有效范围,避免了很多不必要的编译错误,同时依然保证了Rust的内存安全。
内容的提问来源于stack exchange,提问作者venkysmarty
相关产品推荐
相关产品推荐

