函式呼叫中的生命週期
除了借用引數,函式也可以傳回借用的值:
#[derive(Debug)] struct Point(i32, i32); fn left_most<'a>(p1: &'a Point, p2: &'a Point) -> &'a Point { if p1.0 < p2.0 { p1 } else { p2 } } fn main() { let p1: Point = Point(10, 10); let p2: Point = Point(20, 20); let p3: &Point = left_most(&p1, &p2); println!("left-most point: {:?}", p3); }
'a
是由編譯器推論的泛型參數。- 生命週期的開頭為
'
,一般預設名稱為'a
。 - 請將
&'a Point
讀做「至少對生命週期a
有效的借用Point
」。- 如果參數位於不同的範圍,「至少」一詞就至關重要。
在上述範例中,請嘗試下列操作:
-
將
p2
和p3
的宣告移至新範圍 ({ ... }
),會產生以下程式碼:#[derive(Debug)] struct Point(i32, i32); fn left_most<'a>(p1: &'a Point, p2: &'a Point) -> &'a Point { if p1.0 < p2.0 { p1 } else { p2 } } fn main() { let p1: Point = Point(10, 10); let p3: &Point; { let p2: Point = Point(20, 20); p3 = left_most(&p1, &p2); } println!("left-most point: {:?}", p3); }
請注意,這在
p3
超越p2
並繼續留存後,就沒有編譯。 -
重設工作區,並將函式簽章變更為
fn left_most<'a, 'b>(p1: &'a Point, p2: &'a Point) -> &'b Point
。這不會編譯,因為生命週期'a
和'b
之間的關係不明確。 -
另一種說明方式:
- 函式會借用兩個值的兩個參照,而函式會傳回另一個參照。
- 該參照必須來自這兩種輸入來源的其中之一 (或來自全域變數)。
- 究竟是哪一個來源?編譯器需要知道來源為何,因此在呼叫點上,所傳回參照的使用時間不會長於來自參照來源的變數。