为什么我不能通过可变值的可变引用的不可变引用来更新值?

1 rust

我发现以下内容很难理解:

fn main() {
    let mut x: i32 = 10;
    {
        let y: &mut i32 = &mut x;
        *y += 10;
        println!("y={}", *y);
        let z: &&mut i32 = &y;

        // z += 10; // error[E0368]: binary assignment operation `+=` cannot be applied to type `&mut i32`
        // *z += 10; // binary assignment operation `+=` cannot be applied to type `&mut i32`
        // **z += 10; //cannot assign to data in a `&` reference
    }
    println!("x={}", x);
}
Run Code Online (Sandbox Code Playgroud)

当我包含 时*z += 10,错误消息是:

fn main() {
    let mut x: i32 = 10;
    {
        let y: &mut i32 = &mut x;
        *y += 10;
        println!("y={}", *y);
        let z: &&mut i32 = &y;

        // z += 10; // error[E0368]: binary assignment operation `+=` cannot be applied to type `&mut i32`
        // *z += 10; // binary assignment operation `+=` cannot be applied to type `&mut i32`
        // **z += 10; //cannot assign to data in a `&` reference
    }
    println!("x={}", x);
}
Run Code Online (Sandbox Code Playgroud)

这与y += 10;

既然*z有类型&mut i32,与 相同y,为什么可以*y用来更新 的值x,但**z不能呢?

tre*_*tcl 5

mut是缩写unique

“可变”和“唯一”之间的界限很模糊,但在这种情况下“可变”可能会导致错误的直觉。&mut引用确实是唯一的引用:它们不能使用别名。如果您有 a &mut T,您知道当引用存在时,将不会通过任何其他引用T访问(无论是改变还是只是读取) 。

(虽然您通常需要唯一的引用来改变值,但有些引用允许别名和突变。&Cell<T>其中之一是:您不需要对 a 进行唯一访问Cell来改变其内容。&mut引用始终是唯一的。)

编译器可以利用引用不能使用别名的知识&mut来执行优化。Rustonomicon 的别名部分有更多详细信息。

&参考文献是共享参考文献

&另一方面,引用总是可以被其他&引用别名。任何需要对 a 进行唯一访问的内容都T必须保证不能使用其他引用来访问T。但 a&&mut T不能保证这一点,因为它可能被另一个 别名——不会保留&&mut T对 a 的独占访问。T但您仍然可以使用 a&&mut T来获取常规&T,因为这不需要对&mut T.

当然,这都是由 Rust 的类型系统强制执行的。考虑如何定义Deref和:DerefMut

  1. Deref::deref接受&self并返回&Self::Target。因此,您不需要对 的唯一访问权限self即可获得对 的共享访问权限*self
  2. DerefMut::deref_mut需要&mut self返回&mut Self::Target。因此,您确实需要唯一的访问权限才能self获得对 的唯一访问权限*self

还有一件事阻止您&mut T通过简单地取消引用 a 来获得 a &&mut T

  1. &mut参考文献没有实现Copy