邁向 Rust

生命週期與生命週期標註(lifetimes)

Rust 程式裡的每個值都存在某段時間——在某一點被建立、在另一點被釋放。生命週期不過是這段時間的名字:某個特定的值(以及任何借用它的參考)有效的那段程式區間。生命週期之所以重要,是因為借用檢查器最一心想防的那個錯誤:一個比它所指向之物活得更久的參考,這在 C 裡就是指向已釋放記憶體的懸置指標。參考只在它所借的值仍存活時才健全,所以編譯器必須推理誰的生命週期比較長。

大多數時候編譯器會自己算出生命週期,你根本不用寫——它看到值在哪裡建立與釋放、參考在哪裡使用,並默默檢查沒有任何參考逃出它所指對象的生命週期。生命週期標註,用一個撇號寫成像 'a(讀作 a 撇 a),只在編譯器無法判斷一個回傳的參考來自哪個輸入時才出現。想想一個接收兩個字串參考、回傳其中之一的函式:編譯器需要知道回傳的參考是借自第一個引數還是第二個,才知道結果有效多久。你的回答方式是命名一個生命週期,把輸入與輸出綁在一起,例如 fn longest<'a>(x: &'a str, y: &'a str) -> &'a str,意思是三者共享生命週期 'a——回傳的參考只在兩個輸入都還活著時才有效。這個標註並不改變任何東西活多久;它只是描述關係,好讓借用檢查器能驗證它。

為何重要與一句誠實的提醒:生命週期是 Rust 在編譯期保證 C 做不到那項性質的方法——你永遠不可能持有一個指向已釋放或已離開範圍記憶體的參考。那就是懸置參考這個錯誤家族的消失,且零執行期成本。誠實的部分是:生命週期標註是初學者覺得最令人困惑的功能,一部分因為語法精簡,一部分因為很容易誤以為你是在「選擇」某樣東西活多久。你不是——你只是在替本來就存在的時間段貼標籤,好讓編譯器能把它們對應起來。深入的機制屬於後面的卷;這裡的重點只是:生命週期是一個值有效的那段時間,而參考絕不可比它活得更久。

// 'a 表示:回傳的參考存活的時間,和兩個輸入一樣久。 fn longest<'a>(x: &'a str, y: &'a str) -> &'a str { if x.len() > y.len() { x } else { y } }

標註描述結果借自哪個輸入;它並不延長任何生命週期。

生命週期標註絕不會讓一個值活得更久——它只是陳述一個關係,再由借用檢查器去驗證。若這個關係無法成立,解法是重新組織所有權,而非加更多標註。

又称
lifetime'alifetime parameter生命週期生命週期參數