函数调用中的生命周期

除了借用其参数之外,函数还可以返回借用的值:

#[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!("p3: {p3:?}");
}
  • 'a 是一个泛型形参,由编译器推断出来。
  • ''a 开头的生命周期是典型的默认名称。
  • &'a Point 读取为“借用的 Point,至少 在 a` 生命周期内有效。
    • 当参数在不同的作用域时,“至少”部分至关重要。

在上述示例中,请尝试以下操作:

  • 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!("p3: {p3:?}");
    }

    请注意:由于 p3 的生命周期比 p2 长,因此无法编译。

  • 重置工作区,然后将函数签名更改为 fn left_most<'a, 'b>(p1: &'a Point, p2: &'a Point) -> &'b Point。这不会被编译,因为 'a'b 生命周期之间的关系不明确。

  • 另一种解释方式:

    • 对两个值的两个引用被一个函数借用,该函数返回 另一个引用。
    • 它必须是来自这两个输入中的一个(或来自一个全局变量)。
    • 是哪一个呢?编译器需要知道这一点,因此在调用点,返回的引用 的使用时间不会超过引用的来源中的变量。