2017-07-14 130 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.