Day 5:生命週期註標
學習目標
- 理解為何需要生命週期(lifetime)
- 學會寫生命周期註標
'a - 讓借用安全地被編譯器驗證
今日重點
問題:回傳哪個借用?
fn longest(x: &str, y: &str) -> &str {
if x.len() > y.len() { x } else { y }
}
編譯器不知道回傳的引用該跟 x 還是 y 綁在一起。需要註標告訴它。
生命週期註標 'a
fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
if x.len() > y.len() { x } else { y }
}
「x、y、回傳值的生命週期都必須至少跟
'a一樣長」— 讓編譯器檢查借用不會懸垂。
結構體中的生命週期
struct ImportantExcerpt<'a> {
part: &'a str, // 這個借用必須存活跟結構體一起
}
impl<'a> ImportantExcerpt<'a> {
fn level(&self) -> i32 { 3 }
}
fn main() {
let novel = String::from("Call me Ishmael. Some years ago...");
let first_sentence = novel.split('.').next().unwrap();
let excerpt = ImportantExcerpt { part: first_sentence };
println!("{}", excerpt.part);
}
練習
// 1. 為何下面會出錯?試著加上生命週期註標修好:
// fn first_word(s: &str) -> &str { ... }
// 2. 兩個引用有不同生命週期:
fn take_longer<'a, 'b>(x: &'a str, y: &'b str) -> &'a str { x }
自我檢查
- 能解釋生命週期解決的問題(懸垂引用)
- 會寫函式生命週期註標
<'a> - 知道結構體持有引用時也要生命週期參數
- 知道多半情況靠「生命週期省略規則」不需寫
深入連結
- The Book 第 10 章「Lifetimes」