Rust中对象可变引用与成员可变引用的冲突疑问
问题解答:Rust子对象可变引用的借用规则差异
这是Rust的非 lexical lifetimes(NLL,非词法生命周期)机制在起作用,核心是看引用的活跃范围(最后一次被使用的位置),而不是变量是否被"使用过"。
第一个可编译示例的原因
#[derive(Debug)] struct Value { value: i32, } #[derive(Debug)] struct Container { value: Value, value2: i32, } fn main() { let mut obj1 = Container { value: Value { value: 12 }, value2: 1 }; let mut_ref1 = &mut obj1; let mut_ref2 = &mut obj1.value; mut_ref2.value = 1; }
你创建mut_ref1后,紧接着就创建了mut_ref2,但**mut_ref1在mut_ref2创建之后再也没有被使用过**。NLL会自动推断mut_ref1的活跃范围到mut_ref2创建前就结束了——相当于mut_ref1在你拿到mut_ref2的时候就已经"失效"了,两个可变引用的活跃范围没有重叠,自然不会违反Rust的可变引用规则。
第二个不可编译示例的原因
#[derive(Debug)] struct Value { value: i32, } #[derive(Debug)] struct Container { value: Value, value2: i32, } fn main() { let mut obj1 = Container { value: Value { value: 12 }, value2: 1 }; let mut_ref1 = &mut obj1; let mut_ref2 = &mut obj1.value; mut_ref1.value2 = 111; }
这里你最后使用的是mut_ref1,这意味着mut_ref1的活跃范围一直持续到赋值语句mut_ref1.value2 = 111。而mut_ref2是对obj1.value的可变引用,mut_ref1作为整个obj1的可变引用,理论上可以修改obj1的所有字段(包括value),这就导致两个可变引用的活跃范围重叠了——Rust的借用检查器会认为这可能引发数据竞争,所以直接报错。
关键总结
Rust的可变引用规则不是"只要创建了多个可变引用就报错",而是同一时间内不能有重叠的可变引用。NLL会根据引用的最后使用位置来缩小活跃范围,避免不必要的报错,但如果两个可变引用的活跃范围确实重叠(比如第二个例子中mut_ref1还在被使用时,mut_ref2还活着),就会触发规则限制。
内容的提问来源于stack exchange,提问作者silverwen
相关产品推荐
相关产品推荐

