Rust 基礎(02) 所有權
所有權
什麼是所有權
Rust的一套內存管理規則。
這套規則是什麼
- 每一個值都有一個變量作爲他的所有者
- 一個值在任何時間都只有一個所有者
- 值的所有者離開作用域之後會被銷燬
作用域
與其他語言的作用域相同,只要還能調用這個變量,那麼他就依舊處於作用域內。
轉移
當把一個變量直接賦值給另一個變量的時候所有權會發生轉移,如下面的代碼:
let b: String = String::from("hello world");
let a: String = b;
當使用 b
給 a
賦值之後 b
會失去對 hello world
的所有權,及在 let a: String = b;
這個語句之後你講無法再調用 b
,因爲他的所有權已經被轉移給 a
(b
也活到了頭)。因此,在 Rust 當中賦值的另一個說法叫做綁定————這就是無GC還無需手動釋放內存的原因。但是這樣的情況只會出現在那些非標量的變量間賦值的時候,如下面這樣的代碼卻不會出現所有權轉移:
let b: i32 = 13;
let a: i32 = b;
這是因爲 a, b 都是標量,直接把13賦值給 a 並不會產生額外的內存開銷。
函數&所有權&借用
如果你把一個變量當作參數傳遞到函數當中,其所有權也會轉移到函數當中,如下面的代碼。
fn main(){
let str: String = String::from("hello world");
printString(str);
}
fn printString(s: String){
println!("{}", s);
}
當 printString
被調用之後,str
的所有權轉移到 printString
函數當中的 s
身上,當 printString
執行結束,s
離開作用域,其所有權被銷燬(並沒有歸還 str
),所以當 printString
調用結束之後 str
也無法再被使用。但這並不是我們期望的結果,我們希望的是在函數當中用完之後所有權能歸還原本的所有者,所以可以使用下面這兩種方式:
// 借用,在數據類型前加一個 &,在函數調用完成之後會歸還所有權
fn printString_1(s: &String){
println!("{}", s);
}
// 把獲得的所有權返回回去(記得使用原本的所有者接收返回值)
fn printString_2(s: String)-> String{
println!("{}", s);
s
}
補充說明
在上一章的變量聲明當中,有一點我們沒有提及:通過 let a: u32 = 9;
這種方式定義的變量是不允許被修改的,如果你需要這個變量可修改,那麼你可以通過 mut
關鍵字來讓這個變量可修改:let mut a: u32 = 9;
。同樣的,在參數傳遞當中 s: String
這樣的參數聲明(形參 parameter)就是在向你傳達一個意思:我雖然把自己傳遞進來了,但是不代表我允許你對我進行修改,如果你希望傳遞進來的值是可以被修改的那麼就應該這樣定義形參:mut s: &String
。