在 Rust 中,何时需要指定显式生命周期?

13

如果我有两个函数

// implicit
fn foo(x: &i32) {
}

// explicit
fn bar<'a>(x: &'a i32) {
}

什么情况下 foo 会返回错误并且 bar 是正确的函数头?我不确定为什么要显式声明生命周期:

'a 表示“生命周期 a”。从技术上讲,每个引用都有与之关联的某个生命周期,但编译器允许在常见情况下省略它们。

我理解生命周期的含义,但是明确指定生命周期 'a' 对我有什么帮助呢?参考资料是 Rust book

1个回答

11
实际上,你需要编写生命周期注解的主要原因是因为编译器会要求你这样做。它将拒绝未被生命周期省略规则覆盖的函数签名。
我想你可能需要一个简单的例子来说明何时必须使用生命周期。想象一下以下情景:
struct Blah<'a> {
    hoy: &'a u8
}

fn want_a_hoy(blah: &Blah) -> &u8 {
    blah.hoy
}

意图很明显,但编译器无法处理:
<anon>:7:35: 7:38 error: missing lifetime specifier [E0106]
<anon>:7     fn want_a_hoy(blah: &Blah) -> &u8 {
                                           ^~~
<anon>:7:35: 7:38 help: see the detailed explanation for E0106
<anon>:7:35: 7:38 help: this function's return type contains a borrowed value, but 
                        the signature does not say which one of `blah`'s 2 elided 
                        lifetimes it is borrowed from

在这种情况下,注释解决了问题:
fn want_a_hoy<'a, 'b>(blah: &'b Blah<'a>) -> &'a u8 {
    blah.hoy
}

在这里,您正在两次指定'a(在Blah<'a>和&'a上)。 这是相同的生命周期! 因此,您对编译器说的是:“此函数接受对包含内部引用的blah的引用。我将返回与blah的内部引用完全一样长的东西。” 在这种情况下,签名强烈暗示您可能会返回来自blah内部的东西。

5
一个更简单的例子,生命周期省略会失败,即 fn pick_one(a: &T, b: &T) -> &T(即使它始终无条件地返回其中一个)。 - user395760

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