[英]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
mut
是unique
缩写 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. Rustonomicon的Aliasing部分提供了更多详细信息。
&
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: 考虑一下如何定义
Deref
和DerefMut
:
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
共享访问。 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
:
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);
}
y
to be mutable -> let mut y
. y
是可变的-> let mut y
。 &y
to be mutable -> ... = &mut y
. &y
是可变的-> ... = &mut y
。 &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);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.