为什么Rust同函数内可存在多个指向同一值的可变引用?
问题原因
你对可变引用独占规则的理解本身没有问题,这段代码能正常编译是Rust的**非词法生命周期(Non-Lexical Lifetimes, NLL)**特性导致的,这是编译器对引用生命周期检查的优化,实际的生命周期判定规则比你预想的更灵活。
具体分析
Rust的可变引用独占规则明确要求:同一时间只能有一个指向同一块内存的存活可变引用,但从Rust 1.31版本(对应Rust 2018 edition)开始,编译器默认启用NLL,引用的生命周期不再死板绑定到变量声明的词法作用域(也就是变量所在的大括号范围),而是会自动计算引用最后一次被使用的位置,超过这个位置引用就会被标记为失效。
对应你代码里的main函数逻辑:
let t = m.get_ref();拿到scores的可变引用t.push(99);是t的最后一次使用,在这行之后,t持有的可变引用已经被编译器判定为失效- 后续调用
println!("{:?}", m);、m.push(56);时,已经没有其他存活的可变引用指向scores,自然不会违反独占规则,编译可以通过。
验证方法
你可以修改代码,在m.push(56)之后再使用一次t,就能触发预期的编译错误:
let t = m.get_ref(); t.push(99); println!("{:?}", m); m.push(56); t.push(88); // 新增这行,此时t的生命周期需要延续到这里,和m.push获取的&mut self引用冲突,编译报错
补充说明
如果是在未启用NLL的旧版本Rust(1.31之前,或者手动使用Rust 2015 edition且关闭NLL)中,你的代码确实会报错,因为旧规则下t的生命周期会持续到main函数结束,和后续m的可变引用冲突。你使用的1.50版本已经默认启用NLL,所以不会报错。
内容的提问来源于stack exchange,提问作者sateesh
相关产品推荐
相关产品推荐

