0


【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

解释:*

fnlonger(s1:&str, s2:&str)->&str{if s2.len()> s1.len(){
        s2
    }else{
        s1
    }}fnmain(){let r;{let s1 ="rust";let s2 ="ecmascript";
        r =longer(s1, s2);}println!("{} is longer", r);}

longer 函数取

s1

s2

两个字符串切片中较长的一个返回其引用值。

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

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

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

3、生命周期注释

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

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

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

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

fnlonger<'a>(s1:&'astr, s2:&'astr)->&'astr{if s2.len()> s1.len(){
        s2
    }else{
        s1
    }}

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

fnmain(){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、结构体中使用字符串切片引用

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

fnmain(){structStr<'a>{
        content:&'astr}let s =Str{
        content:"string_slice"};println!("s.content = {}", s.content);}//运行结果:s.content = string_slice

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

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

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

5、静态生命周期

生命周期注释有一个特别的:

'static


**所有用双引号包括的字符串常量所代表的精确数据类型都是

&'static str

。**

'static

所表示的生命周期从程序运行开始到程序运行结束,就相当于其他语言中的静态全局变量。

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

函数如下:

usestd::fmt::Display;fnlongest_with_an_announcement<'a,T>(x:&'astr, y:&'astr, ann:T)->&'astrwhereT:Display{println!("Announcement! {}", ann);if x.len()> y.len(){
        x
    }else{
        y
    }}

这段程序出自 《Rust 圣经》,是一个同时使用了泛型特性生命周期 机制的程序,大家可以体验一下

Rust

这种巧妙的组合,先有个体验,到后面的学习中肯定会用到。


本篇博客复习了前期所有权知识中的引用机制,补充了结构体使用字符类型切片的遗留问题,介绍了生命周期机制并有综合案例讲解。到此 Rust 两大资源管理机制学习完毕,欢迎大家的订阅学习!

本文转载自: https://blog.csdn.net/m0_58618795/article/details/127356414
版权归原作者 微凉秋意 所有, 如有侵权,请联系我们删除。

“【Rust指南】生命周期机制”的评论:

还没有评论