2017-07-14 90 views
1

我有一个可变的字符串变量,以及一个不可变的变量绑定到可变引用的可变字符串变量。为什么变量的可变引用可以使用可变变量?

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而不是第一个变量?

回答

3

因为可变借贷是唯一的你收到此错误:

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变量的变异方法,那么可能仅仅是因为push_str()方法接受&mut的接收方;如果你已经有了&mut则直接使用,但如果你没有一个,那么锈病会自动尝试为您创建一个,这是不可能的,如果变量不是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` 

我在上面的例子中写了“几乎”,因为在这种情况下,还有一个叫做reborrowing的步骤,它基本上确保可调参考可以在这次调用之后再次使用,而不是被移入函数调用中,但这对于这个并不重要回答。

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");被突变所述Stringvariable引用,但它不会影响variable(即结合)本身。


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