为什么在 Rust 中需要明确的生命周期? [英] Why are explicit lifetimes needed in Rust?

查看:29
本文介绍了为什么在 Rust 中需要明确的生命周期?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在阅读 Rust 书的生命周期章节,我遇到了这个命名/显式生命周期的例子:

I was reading the lifetimes chapter of the Rust book, and I came across this example for a named/explicit lifetime:

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 和因此 &fx 变得无效,并且不应分配给 x.

It's quite clear to me that the error being prevented by the compiler is the use-after-free of the reference assigned to x: after the inner scope is done, f and therefore &f.x become invalid, and should not have been assigned to x.

我的问题是,如果不使用 explicit 'a 生存期,例如通过推断非法将引用分配给更广泛的范围(x = &fx;).

My issue is that the problem could have easily been analyzed away without using the explicit 'a lifetime, for instance by inferring an illegal assignment of a reference to a wider scope (x = &f.x;).

在哪些情况下实际上需要显式生命周期来防止释放后使用(或其他一些类?)错误?

In which cases are explicit lifetimes actually needed to prevent use-after-free (or some other class?) errors?

推荐答案

其他答案都有重点(fjh 的具体例子,其中需要显式生命周期),但缺少一个关键的东西:当编译器会告诉你错误时,为什么还需要显式生命周期?

The other answers all have salient points (fjh's concrete example where an explicit lifetime is needed), but are missing one key thing: why are explicit lifetimes needed when the compiler will tell you you've got them wrong?

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

This is actually the same question as "why are explicit types needed when the compiler can infer them". A hypothetical example:

fn foo() -> _ {  
    ""
}

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

Of course, the compiler can see that I'm returning a &'static str, so why does the programmer have to type it?

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

The main reason is that while the compiler can see what your code does, it doesn't know what your intent was.

函数是防火墙更改代码影响的自然边界.如果我们允许从代码中完全检查生命周期,那么看似无害的更改可能会影响生命周期,这可能会在远处的函数中导致错误.这不是一个假设的例子.据我了解,当您依赖顶级函数的类型推断时,Haskell 会遇到这个问题.Rust 将这个特殊问题扼杀在萌芽状态.

Functions are a natural boundary to firewall the effects of changing code. If we were to allow lifetimes to be completely inspected from the code, then an innocent-looking change might affect the lifetimes, which could then cause errors in a function far away. This isn't a hypothetical example. As I understand it, Haskell has this problem when you rely on type inference for top-level functions. Rust nipped that particular problem in the bud.

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

There is also an efficiency benefit to the compiler — only function signatures need to be parsed in order to verify types and lifetimes. More importantly, it has an efficiency benefit for the programmer. If we didn't have explicit lifetimes, what does this function do:

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

不检查源代码就无法判断,这会违背大量的编码最佳实践.

It's impossible to tell without inspecting the source, which would go against a huge number of coding best practices.

通过推断对更广泛范围的引用进行非法分配

by inferring an illegal assignment of a reference to a wider scope

范围生命周期,本质上.更清楚一点的是,生命周期 'a 是一个通用生命周期参数,它可以在编译时根据调用点专门用于特定范围.

Scopes are lifetimes, essentially. A bit more clearly, a lifetime 'a is a generic lifetime parameter that can be specialized with a specific scope at compile time, based on the call site.

是否真的需要显式生命周期来防止 [...] 错误?

are explicit lifetimes actually needed to prevent [...] errors?

完全没有.需要生命周期来防止错误,但需要明确的生命周期来保护那些缺乏理智的程序员所拥有的东西.

Not at all. Lifetimes are needed to prevent errors, but explicit lifetimes are needed to protect what little sanity programmers have.

这篇关于为什么在 Rust 中需要明确的生命周期?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆