什么时候静态生命周期不合适?
我在网上找到了很多关于 Rust 生命周期的信息,包括关于静态生命周期的信息。对我来说,在某些情况下,您必须保证引用将比一切都长,这是有道理的。
例如,我有一个要传递给线程的引用,编译器要求将该引用标记为静态。在这种情况下,这似乎是有道理的,因为编译器无法知道线程将存活多长时间,因此需要确保传递的引用比线程存活的时间更长。(我认为这是正确的?)
我不知道这是从哪里来的,但我总是担心用静态生命周期标记某些东西是值得怀疑的,并在可能的情况下避免。
所以我想知道这是否正确。我应该批评用静态生命周期标记事物吗?是否存在编译器需要一个策略但实际上可能更优化的替代策略的情况?
我可以通过哪些具体方法来推理静态生命周期的应用,并可能确定何时可能不合适?
回答
您可能已经猜到了,对此没有明确的技术性答案。
作为 Rust 的新手, 'static引用似乎违背了借用系统的全部目的,并且有一种避免引用的想法。一旦您获得更多经验,这种想法就会消失。
首先,'static看起来并不坏,因为所有与它们没有其他生命周期相关的事物都是'static,例如String::new()。请注意,'static这并不意味着所讨论的值确实永远存在。它只是意味着该值可制成能长生不老。在您的线程示例中,线程无法对其自己的生命周期做出任何承诺,因此它需要能够让所有传递给它的东西永远存在。任何不包括比'static(例如vec![1,2,3])短的生命周期的拥有价值都可以永远存在(简单地通过不破坏它们)并因此而存在'static。
其次,&'static- 静态引用 - 无论如何都不会经常出现。如果是这样,您通常会知道原因。你不会看到很多fn foo(bar: &'static Bar)因为它的用例并不多,而不是因为它被主动避免。
有些情况'static确实会以令人惊讶的方式出现。意料之外:
- 一个
Box<dyn Trait>是隐含一个Box<dyn Trait + 'static>。这是因为当Box删除内部值的类型时,它可能有与之关联的生命周期;并且所有(不同的)类型必须在Box生命周期内有效。因此,所有类型都需要在它们的生命周期中共享一个公分母,并且 Rust 被定义为选择'static. 这种选择通常没问题,但会导致令人惊讶的“需要 '静态”错误。您可以明确地将其概括为Box<dyn Trait + 'a> - 如果您
impl Drop的类型有自定义,Drop-checker可能无法证明析构函数无法观察已经被删除的值。为了防止Dropimpl 访问对已删除值的引用,编译器要求整个类型仅在其中包含'static引用。这可以通过不安全的实现来克服,它提升了 -'static要求。