在上一篇中,我們深入了解了如何運用所有權系統來設計優雅的 API。
現在我們轉向一個更加深刻的主題:生命週期 (Lifetimes)。
借用雖然強大,但必須遵守一條黃金法則:
引用絕不能比它所指向的資料活得更久。
生命週期是 Rust 中一個抽象的概念,它描述了引用有效性的時間範圍。
每個引用都有一個生命週期,它告訴編譯器:「這個引用在什麼時候是有效的,什麼時候會失效。」
讓我們先看看一個簡單的例子:
fn longest(x: &str, y: &str) -> &str {
if x.len() > y.len() {
x
} else {
y
}
}
fn main() {
let string1 = String::from("abcd");
let result;
{
let string2 = String::from("xyz");
result = longest(&string1, &string2); // result 借用了 string2
} // <-- string2 在這裡被銷毀
println!("最長的字串是 {}", result); // 編譯錯誤!result 指向了一個無效的記憶體
}
編譯器的診斷:
編譯器的邏輯:
longest
函式回傳的引用可能來自 x
或 y
x
和 y
的生命週期可能不同fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
if x.len() > y.len() {
x
} else {
y
}
}
這個 'a
是泛型生命週期參數,它告訴編譯器:
x
和 y
的生命週期都至少和 'a
一樣長'a
x
或 y
中較短的那個活得更久// Rust - 編譯期就阻止問題
fn process_string(s: &str) -> String {
s.to_uppercase()
}
fn main() {
let original = String::from("hello");
let result = process_string(&original);
println!("{}", original); // "hello" - 安全
println!("{}", result); // "HELLO"
// 生命週期問題在編譯期就被阻止
let result2;
{
let temp = String::from("world");
result2 = process_string(&temp);
} // temp 被銷毀
println!("{}", result2); // ❌ 編譯錯誤!
}
生命週期系統體現了 Rust 的「先緊後鬆」哲學:
這種設計讓開發者從「事後除錯」轉向「事前預防」,從根本上改變了我們對記憶體安全的思考方式。
在下一篇中,我們將看到這些概念如何在實際的結構體、方法和靜態生命週期中發揮作用。