什么是lifetime elision(生命周期省略)?简单来说是什么?

20

来自Rust文档

Rust支持在函数体中进行强大的本地类型推断,但它有意不对项目签名进行任何类型推理。然而,出于人性化的考虑,在判断生命周期时会应用一种非常受限的次要推断算法,称为“生命周期省略”。生命周期省略仅关注使用三个易于记忆和明确无误的规则推断生命周期参数。这意味着生命周期省略充当了编写项目签名的简写,同时不会像完全应用于它时的本地推断那样隐藏实际涉及的类型。

我不理解这是什么意思。什么是项目签名?什么是“推断生命周期参数”?一些例子或类比将会很有帮助。

1个回答

41
一个项签名是给出函数的名称和类型的部分,也就是你调用它所需的一切(而不需要知道它是如何实现的);例如:
fn foo(x: u32) -> u32;

这是另一个接受 &str 引用的例子:
fn bar<'a>(s: &'a str) -> &'a str;

在Rust中,所有的引用都有一个附加的生命周期;这是类型的一部分。上述的bar函数不仅表示"这个函数接受一个字符串的引用并返回另一个引用",它还表示"这个函数接受一个字符串引用,并返回另一个引用,该引用有效的时间与给定的引用一样长。这是Rust所有权系统的重要部分。
然而,每次都指定这些生命周期是很麻烦的,因此Rust有"生命周期省略"(即"不显式地写出它们")。这只是为程序员提供方便,这样他们就不必在"显而易见"的情况下编写太多的生命周期。
规则列在书中,但为了完整起见,它们是:
  1. 函数参数中没有其他指定的生命周期是不同的。例如:
fn f(x: &T, y: &U)

意思是:

fn f<'a, 'b>(x: &'a T, y: &'b U)

即没有这些生命周期之间的自动链接。

  1. 如果只有一个输入生命周期,则该生命周期将用于每个输出生命周期。例如:
struct U<'a> {}  // struct with a lifetime parameter

fn f(x: &T) -> &U

变成:

fn f<'a>(x: &'a T) -> &'a U<'a>

否则,如果有多个输入生命周期,但其中一个是&self&mut self(即它是一个方法),那么所有省略的输出生命周期都与self相同。这涵盖了一个常见情况,即方法返回对其字段之一的引用。例如:
impl S {
    fn get_my_item(&self, key: &str) -> &str {}
}

变成:

fn get_my_item<'a,'b>(&'a self, key: &'b str) -> &'a str  // use the self lifetime

文档中还有一些更多的例子。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接