为什么在涉及 += 运算符的同一表达式中使用可变引用和不可变引用有时似乎被允许,有时则不允许?
Why does using a mutable and an immutable reference in the same expression involving the += operator seem to be sometimes allowed, sometimes not?
在下面的代码示例中,我尝试以四种不同的方式通过对它的可变引用来增加结构 X
的成员变量 a
。在这里,编译器为 B
表示的行给出以下错误:
error[E0502]: cannot borrow `*x` as immutable because it is also borrowed as mutable
--> src\main.rs:17:23
|
17 | *x.get_a_mut() += x.get_a(); //B DOESN'T COMPILE
| ------------------^--------
| || |
| || immutable borrow occurs here
| |mutable borrow occurs here
| mutable borrow later used here
如果在同一表达式中使用对 a
的可变引用和不可变引用是一个问题,为什么 C
和 D
可以编译?
struct X {
a: i64,
}
impl X {
pub fn get_a_mut(&mut self) -> &mut i64 {
return &mut self.a;
}
pub fn get_a(&self) -> &i64 {
return &self.a;
}
}
fn my_fn(x: &mut X) {
*x.get_a_mut() += 5; //A
*x.get_a_mut() += x.get_a(); //B DOESN'T COMPILE
*x.get_a_mut() += 2 * x.get_a(); //C
*x.get_a_mut() = x.get_a() + x.get_a(); //D
}
fn main() {
let mut x = X { a: 50 };
my_fn(&mut x);
}
根据 +=
documentation,您在 B
的情况下调用 add_assign(lhs: &mut i64, rhs: &i64)
,在 A
、[=15= 的情况下调用 add_assign(lhs: &mut i64, rhs: i64)
] 和 D
.
在A
的情况下,rhs
是一个常量,不同于x.a
;没问题。
在 C
的情况下,rhs
是临时的(2 * x.get_a()
的结果)并且不需要保留对 x.a
的引用即可存在;没问题。
在 D
的情况下,rhs
是临时的(x.get_a() + x.get_a()
的结果)并且不需要保留对 x.a
的引用即可存在;没问题。
但是当涉及到案例 B
时,rhs
是 对 x.a
的参考;那么此调用同时对同一数据 (x.a
) 使用可变 (lhs
) 和不可变 (rhs
) 引用,这是被禁止的。
您最终可以克隆 rhs
:*x.get_a_mut() += x.get_a().clone()
。
在下面的代码示例中,我尝试以四种不同的方式通过对它的可变引用来增加结构 X
的成员变量 a
。在这里,编译器为 B
表示的行给出以下错误:
error[E0502]: cannot borrow `*x` as immutable because it is also borrowed as mutable
--> src\main.rs:17:23
|
17 | *x.get_a_mut() += x.get_a(); //B DOESN'T COMPILE
| ------------------^--------
| || |
| || immutable borrow occurs here
| |mutable borrow occurs here
| mutable borrow later used here
如果在同一表达式中使用对 a
的可变引用和不可变引用是一个问题,为什么 C
和 D
可以编译?
struct X {
a: i64,
}
impl X {
pub fn get_a_mut(&mut self) -> &mut i64 {
return &mut self.a;
}
pub fn get_a(&self) -> &i64 {
return &self.a;
}
}
fn my_fn(x: &mut X) {
*x.get_a_mut() += 5; //A
*x.get_a_mut() += x.get_a(); //B DOESN'T COMPILE
*x.get_a_mut() += 2 * x.get_a(); //C
*x.get_a_mut() = x.get_a() + x.get_a(); //D
}
fn main() {
let mut x = X { a: 50 };
my_fn(&mut x);
}
根据 +=
documentation,您在 B
的情况下调用 add_assign(lhs: &mut i64, rhs: &i64)
,在 A
、[=15= 的情况下调用 add_assign(lhs: &mut i64, rhs: i64)
] 和 D
.
在A
的情况下,rhs
是一个常量,不同于x.a
;没问题。
在 C
的情况下,rhs
是临时的(2 * x.get_a()
的结果)并且不需要保留对 x.a
的引用即可存在;没问题。
在 D
的情况下,rhs
是临时的(x.get_a() + x.get_a()
的结果)并且不需要保留对 x.a
的引用即可存在;没问题。
但是当涉及到案例 B
时,rhs
是 对 x.a
的参考;那么此调用同时对同一数据 (x.a
) 使用可变 (lhs
) 和不可变 (rhs
) 引用,这是被禁止的。
您最终可以克隆 rhs
:*x.get_a_mut() += x.get_a().clone()
。