为了账号安全,请及时绑定邮箱和手机立即绑定

什么是非词汇生命周期?

/ 猿问

什么是非词汇生命周期?

什么是非词汇生命周期?

铁锈RFC与非词汇生命周期有关已获批准要用语言实现很长一段时间。最近,RUST对这个特性的支持已经改进了很多,并且被认为是完整的。

我的问题是:什么是非词汇生命?


查看完整描述

3 回答

?
慕运维8079593

通过理解什么是非词汇生命周期是最容易理解的。词法一生都是如此。在非词法生命周期存在之前的Rust版本中,此代码将失败:

fn main() {
    let mut scores = vec![1, 2, 3];
    let score = &scores[0];
    scores.push(4);}

Rust编译器看到scoresscore变量,因此它不允许进一步的变异scores:

error[E0502]: cannot borrow `scores` as mutable because it is also borrowed as immutable
 --> src/main.rs:4:5
  |
3 |     let score = &scores[0];
  |                  ------ immutable borrow occurs here
4 |     scores.push(4);
  |     ^^^^^^ mutable borrow occurs here
5 | }
  | - immutable borrow ends here

然而,一个人可以很小地看出这个例子过于保守:score从未使用过!问题是scores通过score词法-它一直持续到包含它的区块的尽头:

fn main() {
    let mut scores = vec![1, 2, 3]; //
    let score = &scores[0];         //
    scores.push(4);                 //
                                    // <-- score stops borrowing here}

非词法生命周期通过增强编译器来理解这个层次的细节来解决这个问题。编译器现在可以更准确地判断何时需要借用,这段代码将编译。

非词汇生命周期的一个奇妙之处是,一旦启用,没有人会想到他们..它只会变成“铁锈做什么”,事情会(希望)只是起作用。

为什么允许词汇生命周期?

锈蚀只允许已知的安全程序编译.然而,这是不可能的完全允许安全程序和拒绝不安全程序。为此,锈斯特犯了保守的错误:一些安全程序被拒绝。词汇生命周期就是一个例子。

词汇生命周期在编译器中更容易实现,因为块的知识“微不足道”,而对数据流的了解则较少。编译器需要改写为引入并使用“中级代表”(MIR)..然后是借阅支票。)必须重写以使用MIR,而不是抽象语法树(AST)。然后,借用检查器的规则必须细化,以便更细粒度。

词汇生命周期并不总是妨碍程序员的工作,而且有很多方法可以绕过词汇生命周期,即使它们很烦人。在许多情况下,这需要添加额外的大括号或布尔值。这使得Rust 1.0能够发布,并且在非词法生命周期实现之前的许多年中都是有用的。

有趣的是好的模式的发展是因为词汇的生命周期。对我来说最主要的例子是这个entry花纹..此代码在非词法生存期之前失败,并使用它进行编译:

fn example(mut map: HashMap<i32, i32>, key: i32) {
    match map.get_mut(&key) {
        Some(value) => *value += 1,
        None => {
            map.insert(key, 1);
        }
    }}

但是,此代码效率低下,因为它两次计算密钥的散列。创建的解决方案因为词汇生命周期更短、效率更高:

fn example(mut map: HashMap<i32, i32>, key: i32) {
    *map.entry(key).or_insert(0) += 1;}

“非词汇一生”这个名字听起来不对

值的生存期是该值停留在特定内存地址的时间跨度(请参阅为什么我不能将值和对该值的引用存储在同一个结构中?更详细的解释)。被称为非词法生命周期的特性变化任何值的生命周期,所以它不能使生命周期非词汇化.它只会使这些值的借方的跟踪和检查更加精确。

该功能的一个更准确的名称可能是“非词法”。借来一些编译器开发人员提到了底层的“基于和平号的借用”。

非词汇生命周期从来就不是一个“面向用户”的特性,本身..他们大多在我们的脑海中长大,因为我们从他们的缺席中得到的小剪纸。它们的名称主要是为了内部开发目的,而为营销目的而更改名称从来就不是优先事项。

是啊,但我该怎么用呢?

在Rust 1.31(2018-12-06年发布)中,您需要选择加入Cargo.toml中的Rust 2018版本:

[package]name = "foo"version = "0.0.1"authors = ["An Devloper <an.devloper@example.com>"]edition = "2018"

如果你还在使用2015版的话,非词汇的生命周期还不能在稳定的锈蚀中使用。在Rust的夜间版本中,您可以通过以下特性选择NLL:

#![feature(nll)]

您甚至可以使用编译器标志选择进入NLL的实验版本。-Z polonius.

一个用非词汇生命周期解决实际问题的例子


查看完整回答
反对 回复 2019-06-19
?
一只名叫tom的猫

这当然是一种可能性。在一组约束范围内进行设计(即使是任意的!)能带来新的有趣的设计。没有这些限制,我们可能会回到我们现有的知识和模式,永远不会学习或探索,以找到新的东西。话虽如此,想必有人会认为“哦,哈希是计算了两次,我可以修正它”,然后API就会被创建,但是用户可能一开始就很难找到API。我希望像这样的工具克里皮帮助那些人。

查看完整回答
反对 回复 2019-06-19
?
冉冉说

我认为值得强调的是,也许反直觉地说,非词汇生命周期不是关于变量的生命周期,而是关于Borrow的生命周期。或者,换句话说,非词汇生命周期是指将变量的生命周期与借词的寿命联系起来.除非我错了?(但我不认为在执行析构函数时NLL会发生变化) –

查看完整回答
反对 回复 2019-06-19
  • 3 回答
  • 0 关注
  • 91 浏览
我要回答

添加回答

回复

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信