函式呼叫中的生命週期

除了借用引數,函式也可以傳回借用的值:

#[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」。
    • 如果參數位於不同的範圍,「至少」一詞就至關重要。

在上述範例中,請嘗試下列操作:

  • p2p3 的宣告移至新範圍 ({ ... }),會產生以下程式碼:

    #[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 之間的關係不明確。

  • 另一種說明方式:

    • 函式會借用兩個值的兩個參照,而函式會傳回另一個參照。
    • 該參照必須來自這兩種輸入來源的其中之一 (或來自全域變數)。
    • 究竟是哪一個來源?編譯器需要知道來源為何,因此在呼叫點上,所傳回參照的使用時間不會長於來自參照來源的變數。