简体   繁体   English

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

[英]Why can't I update a value through an immutable reference of a mutable reference of a mutable value?

I found the following hard to understand: 我发现以下内容很难理解:

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);
}

When I include *z += 10 , the error message is: 当我包含*z += 10 ,错误消息为:

error[E0368]: binary assignment operation `+=` cannot be applied to type `&mut i32`
  --> src/main.rs:10:9
   |
10 |         *z += 10; // binary assignment operation `+=` cannot be applied to type `&mut i32`
   |         --^^^^^^
   |         |
   |         cannot use `+=` on type `&mut i32`
   |
   = help: `+=` can be used on 'i32', you can dereference `*z`: `**z`

which is exactly the same as y += 10; y += 10;完全相同y += 10;

Since *z has the type &mut i32 , which is the same as y , why can *y be used to update the value of x , but **z can't? 由于*z具有&mut i32类型, &mut i32 y相同,为什么*y可以用来更新x的值,但是**z无法?

mut is short for unique mutunique缩写

There's a blurry line between "mutable" and "unique", but "mutable" may lead to the wrong intuition in this case. 在“可变”和“唯一”之间存在模糊的界限,但是在这种情况下,“可变”可能会导致错误的直觉。 &mut references are really unique references: they cannot be aliased. &mut引用实际上是唯一引用:它们不能别名。 If you have a &mut T , you know that while the reference exists , the T will not be accessed (either to mutate or just to read) through any other reference. 如果您有&mut T ,那么您知道当引用存在时 ,将不会通过任何其他引用来访问T (进行突变或只是读取)。

(Although you normally need a unique reference to mutate a value, there are references that allow both aliasing and mutation. &Cell<T> is one: you don't need unique access to a Cell to mutate its contents. &mut references are always unique.) (尽管通常需要使用唯一的引用来对值进行突变,但是有些引用同时允许别名和突变。 &Cell<T>是其中之一:您不需要对Cell进行唯一的访问来对其内容进行突变。 &mut引用始终是唯一的。)

The compiler may use the knowledge that a &mut reference cannot be aliased to perform optimizations. 编译器可能会使用&mut引用不能被别名化的知识来执行优化。 The Aliasing section of the Rustonomicon has some more details. RustonomiconAliasing部分提供了更多详细信息。

& references are shared references &参考是共享参考

& references, on the other hand, can always be aliased by other & references. &引用,而另一方面,总是可以通过其他别名&引用。 Anything that requires unique access to a T must guarantee that no other reference can be used to access the T . 任何需要唯一访问T必须保证不能使用其他引用来访问T But a &&mut T can't guarantee that, because it could be aliased by another &&mut T -- exclusive access to the T is not preserved. 但是&&mut T不能保证,因为它可以被另一个 &&mut T别名-不保留对T独占访问。 But you can still use a &&mut T to get a regular &T , because that doesn't require unique access to the &mut T . 但是您仍然可以使用&&mut T获得常规的&T ,因为这不需要对&mut T唯一访问。

Naturally, this is all enforced by Rust's type system. 自然,这都是由Rust的类型系统强制执行的。 Consider how Deref and DerefMut are defined: 考虑一下如何定义DerefDerefMut

  1. Deref::deref takes &self and returns &Self::Target . Deref::deref接受&self并返回&Self::Target So you don't need unique access to self to get shared access to *self . 因此,您不需要对self进行唯一访问即可获得对*self共享访问。
  2. DerefMut::deref_mut takes &mut self to return &mut Self::Target . DerefMut::deref_mut &mut self返回&mut Self::Target So you do need unique access to self to get unique access to *self . 因此,您确实需要对self唯一访问权限才能获得对*self唯一访问权限。

And one more thing prevents you from getting a &mut T by simply dereferencing a &&mut T : 还有一两件事阻止你得到一个&mut T通过简单地解引用&&mut T

  1. &mut references don't implement Copy . &mut引用不实现Copy

You missed a few mut : 您错过了一些mut

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

        **z += 10;
    }
    println!("x={}", x);
}

playground 操场

  • you want y to be mutable -> let mut y . 您希望y是可变的-> let mut y
  • you want &y to be mutable -> ... = &mut y . 您希望&y是可变的-> ... = &mut y
  • you want to assign it to a &mut z and reference this as mutable => let z: &mut &mut i32 = ... 您想将其分配给&mut z并将其引用为可变=> let z: &mut &mut i32 = ...

I think it's more intuitive when omiting the type: 我认为省略类型会更直观:

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

        **z += 10;
    }
    println!("x={}", x);
}

playground 操场

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 为什么我不能借用可变引用的不可变引用 - Why I can't borrow immutable reference of a mutable reference 当返回对范围之外的值的可变引用的不可变引用时,为什么在范围结束时丢弃了可变引用? - When an immutable reference to a mutable reference to a value outside the scope is returned, why is the mutable reference dropped when the scope ends? 为什么我可以使用可变变量使其生命周期与不可变引用重叠,但我不能以相同的方式使用可变引用? - Why can I use a mutable variable such that its lifetime overlaps with an immutable reference, but I can't use a mutable reference in the same way? 如何对不可变值进行可变引用 - How to make a mutable reference to an immutable value 具有类型或值的可变引用? - Mutable reference with type or value? 为什么 Rust 不能在类型构造函数中强制可变引用到不可变引用? - Why Rust can't coerce mutable reference to immutable reference in a type constructor? 是否可以在模式中创建可变引用的可变值? - Is it possible to create a mutable value of a mutable reference in a pattern? 您不能借用对只读值的可变引用 - You can’t borrow a mutable reference to a read-only value 可以通过引用可变值来移动值吗? - Can a value be moved by taking a mutable reference? 为什么我不能通过迭代器可变引用对切片进行突变 - Why can't I mutate a slice via iterator mutable reference
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM