单引号(')表示的是什么标识符?

180

我在Rust中遇到过几种以单引号标记的类型:

'static
'r
'a

那个撇号(')的意义是什么?也许它是引用(&)的修饰符?是针对引用的通用键入方式吗?我不知道这个文档在哪里隐藏。

2个回答

141

这些是Rust的命名生命周期。

引用自The Rust Programming Language

Rust中的每个引用都有一个生命周期,即该引用有效的范围。大部分情况下,生命周期都是隐式和推断出来的,就像大多数情况下类型都是推断出来的一样。与我们必须注明类型因为可能存在多种类型的情况类似,有时引用的生命周期可以以几种不同的方式相关联,因此Rust需要我们使用泛型生命周期参数注释关系,以确保运行时使用的实际引用肯定有效。

生命周期注解不会改变参与的引用存在的时间。就像函数在签名指定通用类型参数时可以接受任何类型一样,当签名指定通用生命周期参数时,函数可以接受具有任何生命周期的引用。 生命周期注解所做的是将多个引用的生命周期相互关联。
生命周期注解具有稍微不同寻常的语法:生命周期参数的名称必须以撇号 ' 开头。生命周期参数的名称通常都是小写字母,并且像通用类型一样,它们的名称通常非常短。 'a 是大多数人默认使用的名称。生命周期参数注解放在引用的 & 后面,并且空格将生命周期注解与引用的类型分隔开来。
换句话说,生命周期近似于引用指向的数据有效的执行范围。 Rust 编译器会保守地推断出最短的生命周期以确保安全。如果您想告诉编译器一个引用的生命周期比最短估计时间更长,您可以命名它,例如,说输出引用具有与给定输入引用相同的生命周期。
“静态”生命周期是一种特殊的生命周期,是所有生命周期中最长的——在程序的整个执行期间都存在。典型的例子是字符串“字面量”,它们将在程序/模块的整个生命周期内始终可用。
您可以从此幻灯片中获取更多信息,从第29页开始阅读。 Rust中的生命周期也深入讨论了生命周期。

58

补充quux00的出色答案,具名生命周期还用于向Rust编译器指示返回的借用变量的来源。

该函数

pub fn f(a: &str, b: &str) -> &str {
  b
}

无法编译,因为它返回了一个借用的值,但没有指定它是从a还是b借用的。

要修复这个问题,您需要声明一个命名的生命周期,并在b和返回类型中使用相同的生命周期:

pub fn f<'r>(a: &str, b: &'r str) -> &'r str {
//      ----              ---         ---
  b
}

并按预期使用它

f("a", "b")

10
如果你想告诉编译器一个引用的生命周期比最短的估计更长,你可以给它命名,例如说输出引用具有与给定的输入引用相同的生命周期。对于 Rust 刚接触的人来说,我需要两个答案才能理解这句话。没有代码示例的话,他们的回答可能不太容易理解,也可能会让你在不理解编译器为什么报错的情况下卡住。 - Kevin
3
我认为我理解这个例子中的所有内容,除了 f<'r>。为什么函数有生命周期规范?整个例子对我来说都是有意义的,即使在函数名称后面没有 <'r>;它添加了什么? - lmat - Reinstate Monica
如果我理解正确,在 Rust 中,您必须指定您借用的值来自哪里。在这个例子中,它从 b 传递了借用,但是当 f 结束时,a 是自由的,这与 a 仍然被借用是不同的。 - Nino Filiu
3
为什么编译器不能自动推断变量b的生命周期,因为它是被返回的变量呢? - Ren
2
@Ren,它可以推断出来,但这将允许未指定的副作用带来不可预见的后果,你必须通过代码来找出你允许了哪些副作用。例如:你在堆上有一个100个元素的数组。你访问第501个元素。数组很好,所以它会增长以适应那个元素。现在你有了一个副作用,原因隐藏在代码或数据中。 - nurettin
显示剩余4条评论

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