当对该变量的可变引用可以使用时,为什么不能使用可变变量?

时间:2017-07-14 16:52:10

标签: rust

我有一个可变的字符串变量,一个不可变的变量绑定到可变字符串变量的可变引用。

let mut string = String::from("test");
let variable: &mut String = &mut string;
variable.push_str(" test");
string.push_str(" test");

这失败了:

error[E0499]: cannot borrow `string` as mutable more than once at a time
 --> src/main.rs:5:5
  |
3 |     let variable: &mut String = &mut string;
  |                                      ------ first mutable borrow occurs here
4 |     variable.push_str(" test");
5 |     string.push_str(" test");
  |     ^^^^^^ second mutable borrow occurs here
6 | }
  | - first borrow ends here
  1. 如果第二个变量不可变,为什么我可以调用push_str
  2. 为什么我可以在第二个变量上调用push_str而不是第一个变量?

2 个答案:

答案 0 :(得分:5)

您收到此错误是因为可变借用是独占的:

let mut string = String::from("test")
let variable = &mut string;

在这里,您可以创建对变量的可变引用;因为可变引用意味着独占访问,现在无法访问原始变量,否则您将违反别名保证。

考虑一下:

let mut string = String::from("test");
{
    let variable = &mut string;
    variable.push_str(" test");
}
string.push_str(" test");

此代码将按预期编译和工作,因为在再次访问原始变量之前,可变引用超出了范围。

您可以阅读有关此in the Rust book的更多信息(请参阅本书第二版的this链接)。

至于为什么你可以在非mut变量上调用mutating方法,很可能只是因为push_str()方法接受&mut的接收器;如果你已经有&mut,那么它会被直接使用,但是如果你没有,那么Rust会自动尝试为你创建一个,如果变量不是mut,这是不可能的:

let mut string = String::from("test");

string.push_str("test");
// equivalent to:
String::push_str(&mut string, "test");  // won't work if `string` is not `mut`

let variable = &mut string;
variable.push_str("test");
// [almost] equivalent to:
String::push_str(variable, "test");  // works because `variable` is already `&mut`

我在上面的示例中写了“几乎”,因为在这种情况下还有另一个称为重新延长的步骤,它基本上确保在此调用之后可以再次使用可变引用而不是移动到函数调用中,但它不会这个答案真的很重要。

答案 1 :(得分:3)

Rust Book很好地解释了问题1:

let mut x = 5;
let y = &mut x;
     

y是对可变引用的不可变绑定,这意味着   你不能约束' y'到其他东西(y = &mut z),但y可以   用于将x绑定到其他内容(*y = 5)。

基本上,variable.push_str(" test");正在改变String引用的variable,但它不会影响variable(即绑定)本身。

编译器错误应解释问题2.