无法分配给 `*x`,因为它是借来的

cannot assign to `*x` because it is borrowed

我的错误代码片段和编译器错误信息:

// code snippet 1:

0 fn main() {
1     let mut x: Box<i32> = Box::new(4);
2     let r: &Box<i32> = &x;
3     *x = 8;
4     println!("{}", r);
5 }
// compiler error info: 

error[E0506]: cannot assign to `*x` because it is borrowed
 --> src/main.rs:3:4
  |
2 |     let r = &x;
  |             -- borrow of `*x` occurs here
3 |     *x = 8;
  |     ^^^^^^ assignment to borrowed `*x` occurs here
4 |     println!("{}", r);
  |                    - borrow later used here

For more information about this error, try `rustc --explain E0506`.

以下代码无法编译,这对我来说很有意义,因为我们不能使引用无效 r

// code snippet 2:

0 fn main() {
1     let mut x: i32 = 0;
2     let r: &i32 = &x;
3     x = 1;
4     println!("{}", r);
5 }

但是 code snippet1compiler error info 对我来说意义不大。

x是栈上指向堆内存段的指针,其内容为4,引用r只借用x(指针不是堆内存段),在第 3 行 *x = 8; 中,我们在这里所做的是更改堆上的内存(而不是堆栈上的指针)。变化发生在堆上,而引用只与堆栈有关,它们没有相互关系。

这个问题有点找茬,但我不是为了争论而争论

如果你觉得我的问题不规范,欢迎指出:)

Change happens on the heap , while reference is only relevant to the stack, they do not interrelate.

这没关系,因为类型系统不适用于信息的“深度”。

就其而言,借用 x 是将整个 x 借用到任何深度,因此禁止在 x 内的任何地方进行任何更改。

出于类型检查的目的,这与 xBox<Vec<_>> 并且 r 被积极用于迭代,导致对内部向量的任何更新都可能使迭代器无效。

(另外 type-wise *x = 8 确实需要首先对框本身进行唯一引用,然后再将其“升级”为对框内容的唯一引用,如您从 the trait implementation)

* 的语义由两个特征决定:

pub trait Deref {
   type Target: ?Sized;
   fn deref(&self) -> &Self::Target;
}

pub trait DerefMut: Deref {
   fn deref_mut(&mut self) -> &mut Self::Target;
}

在你的例子中,当你写 *x = 8 Rust 编译器将表达式扩展到调用中 DerefMut::deref_mut(&mut x),因为 Box<T> 实现了 Deref<Target=T>DerefMut。这就是为什么在行 *x = 8 中执行 x 的可变借用,并且根据孤儿规则它不能完成,因为我们已经在 let r: &Box<i32> = &x;.[=21 中借用了 x =]

Rust 的整个借用模型强制执行一个简单的要求:如果只有一个指针可以访问该位置,则内存位置的内容只能被改变。

在你的例子中,你试图改变的堆位置可以通过 xr 访问——因此改变被拒绝。

此模型使编译器能够执行积极的优化,例如,允许在寄存器 and/or 缓存中存储可通过任一别名访问的值,而无需在读取值时再次从内存中获取。