Rust 生命周期标注积累

Rust 生命周期标注是相当难学的。首先这个概念不方便用语言描述,以至于对"生命周期标注"的精辟总结往往是有歧义的,新手看到时容易纠结,不知道怎么理解对,这增加了学习的难度。其次新手不容易想象"生命周期标注"的使用场景,这种场景也比较复杂,需要学习者对 Rust 生命周期等基础的概念有深刻的理解。而且"生命周期标注"的语义可能是多样的,在不同场景下不完全相同,这意味着这个概念本身内容较多,注定要花更多的时间学习。最后,理解"生命周期标注"最终是要理解 Rust 编译器的行为,这种程序行为是很难用自然语言总结全面、准确的,所以在学习过程中总会觉得存在没有理解清楚的特殊情况。

我曾经多次下定决心要搞懂生命周期标注,但最终都失败了。最近我又遇到了这个概念,打算积累下我实际编程中遇到的情况,不强求总结出任何理解。

结构体定义中的生命周期标识

举一个来自星绽的例子

rust 复制代码
/// The result of a query over the VM space.
pub enum VmQueriedItem<'a> {
    /// The current slot is mapped, the frame within is allocated from the
    /// physical memory.
    MappedRam {
        /// The mapped frame.
        frame: FrameRef<'a, dyn AnyUFrameMeta>,
        /// The property of the slot.
        prop: PageProperty,
    },
    /// The current slot is mapped, the frame within is allocated from the
    /// MMIO memory.
    MappedIoMem {
        /// The physical address of the corresponding I/O memory.
        paddr: Paddr,
        /// The property of the slot.
        prop: PageProperty,
    },
}

/// A struct that can work as `&'a Frame<M>`.
pub struct FrameRef<'a, M: AnyFrameMeta + ?Sized> {
    inner: ManuallyDrop<Frame<M>>,
    _marker: PhantomData<&'a Frame<M>>,
}

这里 pub enum VmQueriedItem<'a> 中的 'a 是生命周期标识,表示 VmQueriedItem 的生命周期。此时 'a 是一个变量,不知道具体的生命周期是什么。但我们知道,VmQueriedItem 和 其字段 FrameRef 拥有同样的生命周期,而 FrameRef 和其字段 PhantomData<&'a Frame<M>> 拥有同样的生命周期。这里的字段一定是引用类型或者包含引用类型,我们关注引用类型的生命周期是为了避免悬垂引用。

当创建 VmQueriedItem 类型时,为了构造其字段,我们会传入引用,传入的引用的实际生命周期决定了 'a 的值,编译器通过 'a 的标识知道所构造的 VmQueriedItem 类型的值的生命周期不能超过 'a(否则 VmQueriedItem 类型的值还活着而其中的引用类型已死)。编译器在编译时会检查这个 VmQueriedItem 类型的值有没有在超过 'a 生命周期的时候被使用,如果有则编译时报错。

相关推荐
学逆向的6 小时前
C 堆区内存管理
c语言·开发语言·网络安全
huoyueyi6 小时前
《融天AI-APP从0到1开发实录》
开发语言·lua
OpenAnolis小助手8 小时前
PHP 两个严重漏洞曝光,龙蜥社区 24 小时完成 3 版本修复
开发语言·操作系统·php·龙蜥社区
阿尼卡~9 小时前
VS Code 配置 C 语言开发环境(Windows 10/11):从 GCC 安装到运行、断点调试,一篇搞定
c语言·开发语言·windows
hhhjhl10 小时前
Undici 跨端三方库仓颉适配全流程
java·开发语言·ubuntu
染指111010 小时前
158.Agent-LangGraph-子图(共享状态和不共享状态模式)
开发语言·人工智能·python·ui·agent·agents
wangchunyu11410 小时前
JAVA JVM内存结构与运行时数据区
java·开发语言·jvm
slongzhang_10 小时前
linux 递归删除源码文件|递归删除目录下 *.js,但排除 *.min.js
linux·开发语言·javascript
云和数据.ChenGuang12 小时前
Python 常见特殊方法详解:__new__、__init__、__del__、__str__、__repr__ 与 __getattribute__
开发语言·人工智能·python·1024程序员节
xyouyuweizhu12 小时前
字节流与字符流:Java IO 的两条主线该怎么选
java·开发语言·python