无法分配给 `*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 snippet1
的 compiler 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
内的任何地方进行任何更改。
出于类型检查的目的,这与 x
是 Box<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 的整个借用模型强制执行一个简单的要求:如果只有一个指针可以访问该位置,则内存位置的内容只能被改变。
在你的例子中,你试图改变的堆位置可以通过 x
和 r
访问——因此改变被拒绝。
此模型使编译器能够执行积极的优化,例如,允许在寄存器 and/or 缓存中存储可通过任一别名访问的值,而无需在读取值时再次从内存中获取。
我的错误代码片段和编译器错误信息:
// 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 snippet1
的 compiler 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
内的任何地方进行任何更改。
出于类型检查的目的,这与 x
是 Box<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 的整个借用模型强制执行一个简单的要求:如果只有一个指针可以访问该位置,则内存位置的内容只能被改变。
在你的例子中,你试图改变的堆位置可以通过 x
和 r
访问——因此改变被拒绝。
此模型使编译器能够执行积极的优化,例如,允许在寄存器 and/or 缓存中存储可通过任一别名访问的值,而无需在读取值时再次从内存中获取。