我在读《铁 rust 书》的lifetimes chapter篇,在我的有生之年,我遇到了这个例子:

struct Foo<'a> {
    x: &'a i32,
}

fn main() {
    let x;                    // -+ x goes into scope
                              //  |
    {                         //  |
        let y = &5;           // ---+ y goes into scope
        let f = Foo { x: y }; // ---+ f goes into scope
        x = &f.x;             //  | | error here
    }                         // ---+ f and y go out of scope
                              //  |
    println!("{}", x);        //  |
}                             // -+ x goes out of scope

我很清楚,编译器阻止的错误是分配给x的引用的use-after-free:内部作用域完成后,f&f.x变得无效,不应该分配给x.

我的问题是,使用explicit 'a的生存期,可以很容易地分析出这个问题,例如,通过推断对更大范围的引用的非法分配(x = &f.x;).

在哪些情况下,在空闲(或其他类)后,需要显式生命周期来阻止使用错误?

推荐答案

其他答案都有要点(fjh's concrete example where an explicit lifetime is needed),但缺少一个关键点:为什么在the compiler will tell you you've got them wrong岁时需要明确的生命周期?

这实际上与"当编译器可以推断出显式类型时,为什么需要显式类型"相同.一个假设的例子:

fn foo() -> _ {  
    ""
}

当然,编译器可以看到我返回的是&'static str,那么程序员为什么要输入它呢?

主要原因是,虽然编译器可以看到你的代码做了什么,但它不知道你的意图是什么.

函数是防止代码更改影响的自然边界.如果我们允许从代码中完全判断生命周期,那么看似无辜的更改可能会影响生命周期,这可能会在遥远的函数中导致错误.这不是一个假设的例子.据我所知,Haskell在顶级函数依赖类型推断时有这个问题. rust 把那个问题扼杀在萌芽状态.

编译器还有一个效率优势——只需解析函数签名即可验证类型和生存期.更重要的是,它对程序员有效率上的好处.如果我们没有明确的生命周期,这个函数做什么:

fn foo(a: &u8, b: &u8) -> &u8

如果不判断源代码就无法判断,这与大量编码最佳实践背道而驰.

通过推断一个更大范围的引用的非法分配

范围基本上是are个生命周期.更清楚地说,lifetime 'a是一个generic lifetime parameter,它可以在编译时根据调用站点使用特定的作用域进行专门化.

是否需要明确的生命周期来防止[…]错误?

一点也不.Lifetimes是防止错误所必需的,但显式的生命周期是保护几乎没有理智的程序员所拥有的东西所必需的.

Rust相关问答推荐

Rust TcpStream不能在读取后写入,但可以在不读取的情况下写入.为什么?

如何在Rust中表示仅具有特定大小的数组

定义采用更高级类型泛型的性状

如何go 除铁 rust 中路径组件的第一项和最后一项?

函数内模块的父作用域的访问类型

一种随机局部搜索算法的基准(分数)

我是否可以在Ruust中修改 struct 实例上的字符串,以使其在修改后具有相同的字符串生存期?

使用Rust WASM读取文件

在 Rust 中,在需要引用 self 的 struct 体方法中使用闭包作为 while 循环条件

如何使用tracing-subscriberRust crate 构建多编写者、全局过滤订阅者

如何处理闭包中的生命周期以及作为参数和返回类型的闭包?

需要一个有序向量来进行 struct 初始化

如何将 &[T] 或 Vec<T> 转换为 Arc<Mutex<[T]>>?

如何在Rust中使用Serde创建一个自定义的反序列化器来处理带有内部标记的枚举

在 Bevy 项目中为 TextureAtlas 精灵实施 NearestNeighbor 的正确方法是什么?

在每个循环迭代中删除borrow

`use std::error::Error` 声明中断编译

为什么这个闭包没有比 var 长寿?

类型组的通用枚举

Rust:为什么在 struct 中borrow 引用会borrow 整个 struct?