我的编程空间,编程开发者的网络收藏夹
学习永远不晚

Rust指南之生命周期机制详解

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

Rust指南之生命周期机制详解

前言

  Rust 生命周期机制是与所有权机制同等重要的资源管理机制,之所以引入这个概念主要是应对复杂类型系统中资源管理的问题。引用是对待复杂类型时必不可少的机制,毕竟在Rust 中复杂类型的数据不能被处理器轻易地复制和计算。但是为什么还有引入生命周期的概念呢,这是因为引用常常会导致非常复杂的资源管理问题。

1、所有权中的垂悬引用解析

先来看一下垂悬引用中所有权的变化:

{
    let ans;

    {
        let x = 5;
        ans = &x;
    }

    println!("ans: {}", ans);
}

这段代码是不会通过 Rust编译器的,原因是 ans 所引用的值已经在使用之前被释放,
borrowed value does not live long enough意为x有效时间太短。

红色区域为 ans的生命周期,绿色区域为 x的生命周期,很显然绿色区域比红色区域小得多,引用必须在值的生命周期以内才有效。

2、结构体中使用String 而不用&str 的原因

用一个函数 longer 解释:

fn longer(s1: &str, s2: &str) -> &str {
    if s2.len() > s1.len() {
        s2
    } else {
        s1
    }
}

fn main() {
    let r;
    {
        let s1 = "rust";
        let s2 = "ecmascript";
        r = longer(s1, s2);
    }
    println!("{} is longer", r);
}

longer 函数取 s1s2 两个字符串切片中较长的一个返回其引用值。

这段代码不会通过编译,原因是返回值引用可能会返回过期的引用:

这段程序中虽然经过了比较,但 r 被使用的时候源值 s1 和 s2 都已经失效了。当然我们可以把 r 的使用移到 s1 和 s2 的生命周期范围以内防止这种错误的发生。

对于函数来说,它并不能知道自己以外的地方是什么情况,它为了保障自己传递出去的值是正常的,必须遵循所有权原则消除一切危险,所以 longer 函数并不能通过编译。

3、生命周期注释

生命周期注释是描述引用生命周期的办法,虽然这样并不能够改变引用的生命周期,但可以在合适的地方声明两个引用的生命周期一致。

生命周期注释用单引号开头,跟着一个小写字母单词:

&i32        // 常规的引用
&'a i32     // 含有生命周期注释的引用
&'a mut i32 // 可变型含有生命周期注释的引用

让我们用生命周期注释改造 longer 函数:

fn longer<'a>(s1: &'a str, s2: &'a str) -> &'a str {
    if s2.len() > s1.len() {
        s2
    } else {
        s1
    }
}

我们需要用泛型声明来规范生命周期的名称,函数返回值的生命周期将与两个参数的生命周期一致

fn main() {
    let r;
    {
        let s1 = "rust";
        let s2 = "ecmascript";
        r = longer(s1, s2);
        println!("{} is longer", r);
    }
}
运行结果:ecmascript is longer

注意:

Rust 自动推导类型的能力很强,如果上面的s1、s2不是字符串切片类型,而是字符串类型的话 r得到的值会在{} 执行完后通过 drop 自动清理掉。

4、结构体中使用字符串切片引用

之前的文章中说过结构体中也是可以使用字符串切片的,那么了解过生命周期的知识后就可以具体设计一个示例了:

fn main() {
    struct Str<'a> {
        content: &'a str
    }
    let s = Str {
        content: "string_slice"
    };
    println!("s.content = {}", s.content);
}
//运行结果:s.content = string_slice

如果对结构体 Str 有方法定义:

impl<'a> Str<'a> {
    fn get_content(&self) -> &str {
        self.content
    }
}

这里返回值并没有生命周期注释,早期 Rust 不支持生命周期自动判断,所有的生命周期必须严格声明,但主流稳定版本的 Rust 已经支持了这个功能,因此可以不加注释。

5、静态生命周期

生命周期注释有一个特别的:'static
所有用双引号包括的字符串常量所代表的精确数据类型都是 &'static str
'static 所表示的生命周期从程序运行开始到程序运行结束,就相当于其他语言中的静态全局变量。

6、泛型、特性与生命周期综合使用

函数如下:

use std::fmt::Display;

fn longest_with_an_announcement<'a, T>(x: &'a str, y: &'a str, ann: T) -> &'a str
    where T: Display
{
    println!("Announcement! {}", ann);
    if x.len() > y.len() {
        x
    } else {
        y
    }
}

这段程序出自 《Rust 圣经》,是一个同时使用了泛型特性生命周期 机制的程序,大家可以体验一下 Rust 这种巧妙的组合,先有个体验,到后面的学习中肯定会用到。

到此这篇关于Rust指南之生命周期机制详解的文章就介绍到这了,更多相关Rust生命周期内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

Rust指南之生命周期机制详解

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

Rust指南之生命周期机制详解

Rust 生命周期机制是与所有权机制同等重要的资源管理机制,之所以引入这个概念主要是应对复杂类型系统中资源管理的问题,这篇文章主要介绍了Rust指南之生命周期机制详解,需要的朋友可以参考下
2022-11-13

rust生命周期详解

生命周期是rust中用来规定引用的有效作用域,在大多数时候,无需手动声明,因为编译器能够自动推导,这篇文章主要介绍了rust生命周期相关知识,需要的朋友可以参考下
2023-03-19

spring之Bean的生命周期详解

Bean的生命周期:Bean的定义——Bean的初始化——Bean的使用——Bean的销毁Bean的定义Bean 是 spring 装配的组件模型,一切实体类都可以配置成一个 Bean ,进而就可以在任何其他的 Bean 中使用,一个 Be
2023-05-31

Android开发之activity的生命周期详解

本文实例讲述了Android activity的生命周期。分享给大家供大家参考,具体如下: activity类处于android.app包中,继承体系如下: 1.Java.lang.Object 2.android.content.Cont
2022-06-06

JVM类加载机制及生命周期的详细介绍

这篇文章主要讲解了“JVM类加载机制及生命周期的详细介绍”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“JVM类加载机制及生命周期的详细介绍”吧!一.目标:1.什么是类的加载?2.类的生命周期
2023-06-02

C++教程之变量的作用域与生命周期详解

在C++编程中,变量的作用域和生命周期是非常重要的概念。了解这些概念可以帮助开发人员编写更好的代码并避免错误。在本文中,我们将探讨C++中变量的作用域和生命周期,以及如何正确地使用它们
2023-05-15

Android编程之基于Log演示一个activity生命周期实例详解

本文实例讲述了Android编程之基于Log演示一个activity生命周期。分享给大家供大家参考,具体如下: 利用Android的Log 演示一个activity的生命周期 代码://DemoActivity.java package u
2022-06-06

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录