• rust生命期


    一、生命期是什么

    生命期,又叫生存期,就是变量的有效期。
    实例1

    {
        let r;
        {
            let x = 5;
            r = &x;
        }
        println!("r: {}", r);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    编译错误,原因是r所引用的值已经被释放。
    在这里插入图片描述

    上图中的绿色范围’a表示r的生命期,蓝色范围’b表示x的生命期。

    实例2

    fn longer(s1: &String, s2: &String) -> &String {
        if s2.len() > s1.len() {
            s2
        } else {
            s1
        }
    }
    fn main() {
        let r;
        {
             let s1 = "rust".to_string();
             let s2 = "ecmascript".to_string();
             r = longer(&s1, &s2);
        }
        println!("{} is longer", r);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    longer函数取s1和s2两个字符串较长的一个返回其引用值。但这段代码不会通过编译,原因是最后使用r的时候,s1和s2都已经失效了。虽然可以把r的使用移到s1和s2的生命期以内避免错误,但对于函数来说,它并不知道调用者如何使用它,所以为了保障自己传递出去的值始终是可使用的,就要消除一切危险,直接不能通过编译。

    所以下面代码编译错误

    fn longer(s1: &String, s2: &String) -> &String {
        if s2.len() > s1.len() {
            s2
        } else {
            s1
        }
    }
    fn main() {
        let r;
        {
             let s1 = "rust".to_string();
             let s2 = "ecmascript".to_string();
             r = longer(&s1, &s2);
            println!("{} is longer", r);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    二、标明生命期

    虽然生命期的含义是变量的有效期,但其实只应用于引用。
    一些场景,必须显式标明引用的生命期。
    标明生命期,并不是改变引用的有效期,只是显式告诉编译器引用的有效期。悬垂引用的问题还存在,还需要程序员自己处理。

    (一)生命期注释是标明引用生命期的办法。
    语法格式:
    用单引号开头,跟着生命期名字:

    &i32 // 常规引用
    &'lifea i32 // 含有生命期注释的引用
    &'lifeb mut i32 // 含有生命期注释的可变引用
    
    • 1
    • 2
    • 3

    (二)特殊生命期

    'static
    
    • 1

    'static表示的生命期是从程序运行开始到程序运行结束。
    所有字符串字面量都是 &'static str

    三、使用生命期

    (一)函数中使用生命期
    改造longer函数:

    fn longer<'a>(s1: &'a String, s2: &'a String) -> &'a String {
        if s2.len() > s1.len() {
            s2
        } else {
            s1
        }
    }
    fn main() {
        let r;
        {
             let s1 = "rust".to_string();
             let s2 = "ecmascript".to_string();
             r = longer(&s1, &s2);
            println!("{} is longer", r);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    我们把生命期作为泛型参数,标明函数返回值的生命期与两个参数的生命期是一样的,这样就能编译通过了。意思是只要返回值和参数的生命期一样时,就能使用longer函数。

    (二)结构体中使用生命期

    fn main() {
        struct Str<'a> {
            content: &'a str
        }
        let s = Str {
            content: "string_slice"
        };
        println!("s.content = {}", s.content);
    }
    
    方法定义
    impl<'a> Str<'a> {
        fn get_content(&self) -> &str {
            self.content
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    这里返回值并没有标明生命期,但是加上也无妨。这是一个历史问题,早期Rust不支持生命期自动判断,所有的生命期必须严格声明,但现在的Rust已经支持了。

  • 相关阅读:
    Uniapp 图片编辑插件 Ba-ImageEditor
    深度学习:多层感知机和异或问题(Pytorch实现)
    Springboot毕设项目高校学科竞赛管理qc6u3(java+VUE+Mybatis+Maven+Mysql)
    数据结构与算法9-排序算法:选择排序、冒泡排序、快速排序
    运维审计是什么意思?有什么作用?用什么软件好?
    「UG/NX」Block UI 选择节点SelectNode
    Python+大数据-知行教育(三)-访问咨询主题看板_增量流程
    Dubbo3入门实践,SpringBoot+Dubbo+Nacos+DubboAdmin
    技术干货| 如何运用 MongoDB 部分索引优化性能问题?
    网上购书(书店)管理系统设计与实现(PHP+Mysql)
  • 原文地址:https://blog.csdn.net/inxunxun/article/details/133365817