Rust 为什么需要生命周期注解

fn main() {
    let b;
    {
        let a = 10;
        b = &a;
    }
    println!("{}", b);
}

此时,a的作用域比b要小。rust的生命周期检查器发现a的生命周期比b要大,但是拥有一个生命周期比它小的对象,编译器就会拒绝编译。简而言之,rust的编译器能帮助我们确定某个引用是否有效(无效的话在编译时就会报错),以此来避免悬垂引用等一系列问题。

然而,现实是,编译器有时候并不能确定某个引用是否有效。我们来看下面这个例子:

fn longest_str(x: &str, y: &str) -> &str {
    if x.len() > y.len() {
        x
    } else {
        y
    }
}

fn main() {
    let str1 = String::from("123");
    let str_longer;
    {
        let str2 = String::from("12345");
        str_longer = longest_str(&str1, &str2);
    }

    println!("{}",str_longer);
}

这段代码是无法编译通过的,报错信息如下:

error[E0106]: missing lifetime specifier
 --> src/main.rs:1:37
  |
1 | fn longest_str(x: &str, y: &str) -> &str {
  |                                     ^ expected lifetime parameter
  |
  = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `x` or `y`

error: aborting due to previous error

For more information about this error, try `rustc --explain E0106`.
error: Could not compile `lifetime_test`.

To learn more, run the command again with --verbose.

表明在函数longest_str里需要生命周期注解,这是为什么呢?我们来分析一下代码。在上面这段代码里,str_longer拥有的引用是否有效呢?答案是不确定。我们只从函数内部来看是无法确认哪个参数的生命周期长或者是短.

需要注意的是,生命周期注解并不改变任何引用的生命周期的长短。也就是说,单个生命周期其实是没什么意义的,生命周期最大的作用就是告诉 Rust 多个引用的泛型生命周期参数如何相互联系的。加入有一个有一个生命周期为'a的参数x,一个生命周期也为'a的参数y,那么就说明x与y的生命周期是一样长的。这么一来就可以解决刚才longest_str函数的问题了。我们给函数标上生命周期注解:

fn longest_str<'a>(x: &'a str, y: &'a str) -> &'a str {
    if x.len() > y.len() {
        x
    } else {
        y
    }
}

fn main() {
    let str1 = String::from("123");
    let str_longer;
    {
        let str2 = String::from("12345");
        str_longer = longest_str(&str1, &str2);
    }

    println!("{}",str_longer);
}

虽然仍然无法编译通过,但是错误信息变成了:

error[E0597]: `str2` does not live long enough
  --> src/main.rs:14:41
   |
14 |         str_longer = longest_str(&str1, &str2);
   |                                         ^^^^^ borrowed value does not live long enough
15 |     }
   |     - `str2` dropped here while still borrowed
16 |
17 |     println!("{}",str_longer);
   |                   ---------- borrow later used here

即错误信息变成了编译器检查出引用生命周期无效了,而不是longest_str这个函数的错误了,即str2和str1生命周期不一致。我们只需要修改main函数里参数的生命周期,使str1与str2生命周期保持一致即可。

fn longest_str<'a>(x: &'a str, y: &'a str) -> &'a str {
    if x.len() > y.len() {
        x
    } else {
        y
    }
}

fn main() {
    let str1 = String::from("12345");
    let str_longer;
    let str2 = String::from("123");
    str_longer = longest_str(&str1, &str2);

    println!("{}",str_longer);
}

那么问题来了,在上面这段代码里,函数longest_str里,x,y和函数返回值的生命周期都是一致的,那我们可不可以将它们标注成不同的呢?就像

fn longest_str<'a, 'b, 'c>(x: &'a str, y: &'b str) -> &'c str {
    if x.len() > y.len() {
        x
    } else {
        y
    }
}

这并没有任何意义, 生命周期注解说到底也只是起一个标识作用.并不会改变程序的任何逻辑.它只是用来给Rust生命周期检查器核对的.

最后,总结一下,当且仅当输出值的生命周期为所有输入值的生命周期交集的子集时,生命周期合法。这个应该很好理解,也很好的解释了我们举的例子中生命周期注解的用法。rust也正是通过这种方式解决了"共享"这一问题,从某种程度上保证了内存的安全。

总结

生命周期注解只是给编译器检查使用的。
注解本身无法改变任何生命周期。
但是标出后能尽量让程序和你预期的一样工作。

(0)

相关推荐

  • 【完整版】使用 Rust 进行嵌入式开发

    作者:RT-Thread社区团队  liukang 原文链接: https://club.rt-thread.org/ask/article/2944.html Rust 是什么 Rust 是一门赋予 ...

  • Python 注解+参数+返回值小结

    这篇文章偏记录类型,不是写的很细.我先说一下什么是注解,就是参数类型的显化操作,而且会给Python赋予一些静态语言的特性. User = strAge = int Answer = str # 其实 ...

  • 感受原著:蒂凡尼早餐(一)

    英国最有影响,销量最大的 Daily Telegraph(每日电讯报)这样评价 "蒂凡尼早餐"这部小说: ("20世纪最浪漫的小说之一") It never o ...

  • Rust基础学习笔记(零):复习基本知识

    由于一个学期没有碰Rust,相关知识殆已忘尽.最近各课逐渐停授,余出时间来从基础重温这些知识,也算是对没有写的基础知识的补充.另外这次复习主要参照了Youtube上的Crush Course视频,两个 ...

  • 员工生命周期管理

    员工的生命周期是什么? 员工生命周期是涵盖了员工与其工作所在组织之间的整个关系,这包括吸引阶段,即人们熟悉公司的过程,一直持续到他们离开组织为止.    在员工与企业之间这种持续关系中,我们分为7个阶 ...

  • 动力电池全生命周期管理

    动力电池全生命周期管理

  • 【原创】基于生命周期的工艺验证之工艺设计阶段

    手把手教您把控技术转移.工艺验证和清洁验证的相互关系学习通道扫描右方二维码即刻报名01 基于生命周期的工艺验证 基于生命周期的工艺验证方法,将工艺研发/设计.商业生产工艺验证.常规商业化生产中控制状态 ...

  • 企业在不同的时期,生存法则是不一样的,如何突破生命周期呢?

    △是新朋友吗?记得先给余导说商点个关注哦- 我们一个人的生命周期有婴儿期, 发育期.青春期.成长期, 然后有可能不长身高了,慢慢步入成熟期. 公司和人一样,也会经历这么一个过程. 每个时期有每个时期不 ...

  • 一文读懂用户全生命周期?

    诸葛君说:诸葛io以用户为中心,打通用户全生命周期数据,构建完整的用户画像并提供营销工具和分析平台,从而为企业实现数据驱动的精准营销和精细化运营提供完整的解决方案. 在诸葛io赋能企业提供精准营销和精 ...

  • 诸葛io CEO孔淼:用户全生命周期 数据赋能下的新营销(附PPT)

    诸葛君说:9月18日,诸葛io CEO孔淼出席WAW X十年数据峰会,并发表主题为<用户全生命周期 数据赋能下的新营销>的演讲,讲述了现在企业面临的获客难,转化低的难题,以及诸葛io三年来 ...

  • 诸葛全面升级「数据接入」,打破数据孤岛,洞察用户全生命周期

    企业数字化的主要特征包括三个方面:第一是连接,连接员工.连接客户.连接机器设备:第二是数据,也就是连接之后实时产生的数据:第三是智能,是数据驱动的智能应用. 2020年,新技术发展的脚步并没有因为疫情 ...

  • 客户全生命周期价值,如何驱动To B业务增长?

    | 全文共 2832 字 | 预计阅读时长 8 分钟 近两年,中国数字经济市场发生了很多变化,随着经济增速持续放缓.人力成本持续攀升,伴随移动互联网的高速发展,倒逼企业重视管理效率的提升,互联网巨头加 ...

  • 企业和产品都有生命周期,如何在倒下之前找到新的盈利突破点?

    △是新朋友吗?记得先给余导说商点个关注哦- 当你开始赚钱,进入成长期, 到了成长期,那么竞争对手一定越来越多. 我们在创业的时候, 你会发现,你是感觉不到竞争对手的. 因为你总是在挑战别人, 你是站在 ...