我发现以下内容难以理解:
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);
}
当我包含*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`
与y += 10;
由于*z
的类型为&mut i32
,与y
相同,所以为什么可以使用*y
来更新x
的值,但是**z
不能?
答案 0 :(得分:3)
mut
是unique
的缩写“可变”和“唯一”之间存在模糊的界线,但是在这种情况下,“可变”可能会导致错误的直觉。 &mut
引用实际上是唯一引用:它们不能别名。如果您有&mut T
,则知道在引用存在的情况下,T
将不会通过 any <进行访问(无论是变异还是只是读取) / em>其他参考。
(尽管通常需要一个唯一的引用来变异一个值,但是有些引用同时允许别名和突变。&Cell<T>
是其中之一:您不需要唯一访问Cell
来变异它的内容。&mut
引用始终是唯一的。)
编译器可能会使用以下知识:不能引用&mut
引用来进行优化。 Aliasing section of the Rustonomicon有更多详细信息。
&
引用是共享引用 &
引用始终可以被其他&
引用作为别名。任何需要对T
进行唯一访问的内容都必须保证不能使用其他引用来访问T
。但是&&mut T
不能保证,因为它可能被另一个 &&mut T
别名-不保留对T
的独占访问。但是您仍然可以使用&&mut T
来获得常规的&T
,因为这不需要对&mut T
的唯一访问。
自然,这都是由Rust的类型系统强制执行的。考虑如何定义Deref
和DerefMut
:
Deref::deref
接受&self
并返回&Self::Target
。因此,您无需拥有对self
的唯一访问权限即可获得对*self
的共享访问权限。DerefMut::deref_mut
以&mut self
返回&mut Self::Target
。因此,您要做需要对self
的唯一访问权限才能获得对*self
的唯一访问权限。还有一件事情使您仅通过解除引用&mut T
就可以阻止您获得&&mut T
:
&mut
引用未实现Copy
。答案 1 :(得分:-1)
您错过了一些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
可变-> let mut y
。&y
可变-> ... = &mut y
。&mut z
并将其引用为可变=> let z: &mut &mut i32 = ...
我认为省略类型会更直观:
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);
}