首页 > 解决方案 > 循环中的多个可变引用

问题描述

我正在尝试更详细地了解 Rust 的所有权和生命周期,但我对这段代码感到非常困惑:

let mut lst = vec![1, 2, 3];
let mut x = &mut 0;

for value in &mut lst {
    *value += 1;
    *x += 1;
    x = value;
}

*x += 1;
println!("{:?}", &lst);

据我了解,Rust 不允许对任何值有多个可变引用,并且对向量中元素的可变引用也借用了向量本身。因此,不可能同时对向量中的两个元素进行可变引用。

lst但是在上面的代码中,循环体存储了对循环外部元素的可变引用x。然后,在下一次迭代中,它需要另一个对 in 中不同元素的可变引用lst,同时给我两个对列表中两个元素的可变引用。

所以我的问题是:为什么允许这样做?

标签: rustlifetimeownership

解决方案


虽然 Rust 不允许你对同一个值有多个可变引用,但它确实允许你对同一个值的非重叠部分有可变引用。

例如,您可以将 a 拆分&mut T为每个字段的单独可变引用,借用检查器将为您跟踪这一点:

struct Foo {
    x: i32,
    y: i32,
}

let mut foo = Foo { x: 0, y : 0 };

let foo_mut = &mut foo;
let x = &mut foo_mut.x;
let y = &mut foo_mut.y;

*x = 1;
*y = 2;

println!("x = {:?}", x);     // 1
println!("y = {:?}", y);     // 2
println!("foo = {:?}", foo); // Foo { x: 1, y: 2 }

同样,您可以使用和之&mut [T]类的方法拆分可变切片引用,它们都为您提供了两个不重叠的切片可变引用。split_at_mutsplit_first_mut

事实上,可变切片的迭代可以通过以下方式实现split_first_mut

let mut lst = vec![1, 2, 3];
let mut x = &mut 0;

let mut rest = &mut *lst;
while let Some((value, rest_)) = rest.split_first_mut() {
    rest = rest_;

    *value += 1;
    *x += 1;
    x = value;
}

*x += 1;
println!("{:?}", &lst);

&mut [T]所以(and )的迭代器&mut Vec<T>可以提供多个共存的可变引用,只要这些可变引用指向向量的不同部分并且不重叠。


推荐阅读