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

 更新时间:2022年10月19日 14:18:17   作者:微凉秋意  
Rust 生命周期机制是与所有权机制同等重要的资源管理机制,之所以引入这个概念主要是应对复杂类型系统中资源管理的问题,这篇文章主要介绍了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生命周期内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 深入了解Rust的生命周期

    深入了解Rust的生命周期

    生命周期指的是引用保持有效的作用域,Rust的每个引用都有自己的生命周期。本文将通过示例和大家详细说说Rust的生命周期,需要的可以参考一下
    2022-12-12
  • 详解Rust 修改源

    详解Rust 修改源

    这篇文章主要介绍了Rust 修改源的相关知识,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧
    2024-01-01
  • Rust遍历 BinaryHeap的示例代码

    Rust遍历 BinaryHeap的示例代码

    Rust 的 BinaryHeap 结构体实现了迭代器接口,因此你可以遍历它,如果你想要遍历 BinaryHeap 中的所有元素,你可以使用 .into_iter() 方法将其转换为迭代器,并遍历其中的元素,本文通过实例介绍Rust遍历 BinaryHeap的相关知识,感兴趣的朋友一起看看吧
    2024-04-04
  • rust 包模块组织结构详解

    rust 包模块组织结构详解

    RUST提供了一系列的功能来帮助我们管理代码,包括决定哪些细节是暴露的、哪些细节是私有的,以及不同的作用域的命名管理,这篇文章主要介绍了rust 包模块组织结构的相关知识,需要的朋友可以参考下
    2023-12-12
  • Rust调用函数操作符 . 和 :: 的区别详解

    Rust调用函数操作符 . 和 :: 的区别详解

    在Rust中,.和::操作符都可以用来调用方法,但它们的用法有所不同,所以本文就将详细的给大家介绍一下.和::操作符的区别,感兴趣的同学跟着小编一起来学习吧
    2023-07-07
  • Rust 中的闭包之捕获环境的匿名函数

    Rust 中的闭包之捕获环境的匿名函数

    这篇文章介绍了Rust编程语言中的闭包,包括闭包的定义、使用、捕获环境中的变量、类型推断与注解、与函数的比较以及实际应用,闭包具有捕获环境、类型推断和高效性等特性,是Rust中一个非常强大的工具,感兴趣的朋友一起看看吧
    2025-02-02
  • Rust中GUI库egui的简单应用指南

    Rust中GUI库egui的简单应用指南

    egui(发音为“e-gooey”)是一个简单、快速且高度可移植的 Rust 即时模式 GUI 库,跨平台、Rust原生,适合一些小工具和游戏引擎GUI,下面就跟随小编一起来看看它的具体使用吧
    2024-03-03
  • Rust 中 Deref Coercion讲解

    Rust 中 Deref Coercion讲解

    Rust 的设计理念一向是显式比隐式好,也就是说所有的行为尽量在代码中表现出来,这篇文章主要介绍了Rust 中 Deref Coercion 介绍,需要的朋友可以参考下
    2022-10-10
  • Rust中的Iterator和IntoIterator介绍及应用小结

    Rust中的Iterator和IntoIterator介绍及应用小结

    Iterator即迭代器,它可以用于对数据结构进行迭代,被迭代的数据结构是可迭代的(iterable),所谓的可迭代就是这个数据结构有返回迭代器的方法,这篇文章主要介绍了Rust中的Iterator和IntoIterator介绍及应用,需要的朋友可以参考下
    2023-07-07
  • 详解Rust中泛型的使用

    详解Rust中泛型的使用

    泛型是一种在编写代码时不指定具体类型,而在使用时再确定类型的编程技巧,本文将详细介绍 Rust 中泛型的相关概念和用法,希望对大家有所帮助
    2023-06-06

最新评论