所有權(ownership)
在 C 裡,當你 malloc 一塊記憶體時,語言並不記錄誰該負責釋放它——那是你記在腦中與註解裡的慣例,弄錯了就洩漏或重複釋放。所有權就是 Rust 的答案:它把「誰該負責」這個非正式的概念,變成一條由編譯器追蹤並強制的硬性規則。這個承諾很容易陳述卻出奇地有力:Rust 程式裡的每個值在同一時刻都剛好有唯一的擁有者,而當擁有者消失時,這個值會被自動清理掉。
具體來說,擁有者是一個綁定到某個值的變數。若你寫 let s = String::from("hello"),那麼 s 就擁有那個字串,包括存放它字元的堆積記憶體。這條規則有三部分。第一,每個值有一個擁有它的變數。第二,任一時刻只能有一個擁有者——你不能讓兩個變數同時擁有同一個值(下一條「移動」談的就是這件事)。第三,當擁有者離開範圍——它所在的區塊結束時——Rust 會執行它的清理(稱為 drop)自動釋放這個值的記憶體。你從不寫 free;擁有者範圍的結束,就是那次釋放。所以在函式內建立的 String,會在函式返回時自動釋放,正好就在 C 程式設計師必須記得呼叫 free 的那個時機。
為何重要:所有權是 Rust 其餘安全性所建立其上的那個唯一概念。因為永遠剛好只有一個擁有者,記憶體被釋放的地點與時機也永遠剛好只有一處——所以你不可能重複釋放(只有擁有者釋放,且只一次),也不可能因為純粹忘記而洩漏(範圍結束替你釋放)。這和謹慎的 C 程式設計師靠所有權慣例所遵循的紀律是同一套,只是由編譯器檢查,而非寄望於一行註解。代價是:滿足「唯一擁有者」這條規則會改變你傳遞值的方式,而這正是移動與借用存在的目的。
fn main() { let s = String::from("hello"); // s 擁有這個堆積字串 greet(s); // 所有權「移動」進 greet } // s 已不存在;這裡沒有東西要釋放 fn greet(name: String) { // name 現在擁有它 println!("hi {name}"); } // 範圍結束 -> drop 執行 -> 記憶體釋放
同一時刻一個擁有者;當擁有者的範圍結束時,值會被自動釋放。
所有權談的是釋放的責任,而非誰能讀取值。透過借用,程式裡許多地方可以同時讀取一個值;但只有一處擁有它、並負責清理它。