尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
【Rust自学】10.5. 生命周期 Pt.1:生命周期的定义与意义、借用检查器与泛型生命周期
10.5 生命周期 Pt.1生命周期的定义与意义、借用检查器与泛型生命周期10.5.1. 什么是生命周期Rust 中的每个引用都有自己的生命周期。生命周期的作用是让引用保持有效换句话说它就是引用保持有效的作用域。在大多数情况下生命周期是隐式的、可推断的。如果引用的生命周期可能以不同方式相互关联就必须手动标注生命周期。生命周期可以说是 Rust 与其他语言相比最与众不同的特征因此非常难学。10.5.2. 生命周期的存在意义生命周期存在的主要目的是避免悬空引用。这个概念在 4.4. 引用与借用 中已经讨论过这里重复一下之前的解释在使用指针时非常容易触发一种叫做悬空指针Dangling Pointer的错误。其定义如下一个指针引用了内存中的某个地址而这块内存可能已经被释放并重新分配给其他人使用。如果你引用了某些数据Rust 编译器会保证在引用离开作用域之前数据不会离开作用域。这就是 Rust 确保悬空引用永远不会出现的方式。看这个例子fn main() { let r; { // 小花括号 let x 5; r x; } println!({}, r); }在这个例子中先声明了r但没有初始化。目的是让r存在于小花括号外见注释位置的作用域中。当然Rust 没有Null值所以在初始化之前不能使用r。在小花括号内声明了变量x并赋值为5。下一行把x的引用赋给了r。在那个小花括号作用域结束之后在外面打印了r。这段代码是无效的因为打印r时x已经走出作用域并被销毁了。所以r的值——也就是x所引用的内存地址——现在指向的是已经被释放的内存它所指向的数据也不再是x。这就造成了悬空引用因此编译器会报错。输出error[E0597]: x does not live long enough -- src/main.rs:5:7 | 4 | let x 5; | - binding x declared here 5 | r x; | ^^ borrowed value does not live long enough 6 | } | - x dropped here while still borrowed 7 | println!({}, r); | - borrow later used here报错信息说借用的值活得不够长。这是因为内部花括号作用域结束时x走出了作用域但r有更大的作用域并可以继续使用。为了保证程序安全此时任何基于r的操作都无法正确运行。Rust 通过借用检查器来检查代码是否合法。10.5.3. 借用检查器借用检查器通过比较作用域来判断所有借用是否合法。在上面的例子中借用检查器发现r是对x的引用但r的存活时间比x更长因此会报错。怎么解决这个问题呢很简单让x至少活得和r一样长。fn main() { let x 5; let r x; println!({}, r); }在这种情况下x从第 2 行活到第 5 行r从第 3 行活到第 5 行。因此x的生命周期完全覆盖了r的生命周期程序不会报错。10.5.4. 函数中的泛型生命周期看这个例子fn main() { let string1 String::from(abcd); let string2 xyz; let result longest(string1.as_str(), string2); println!(The longest string is {result}); } fn longest(x: str, y: str) - str { if x.len() y.len() { x } else { y } }string1是String而string2是字符串切片str。这两个值被传入longest函数string1需要先转换成str然后打印返回值。longest的逻辑是比较两个输入参数并返回较长的那个。输出error[E0106]: missing lifetime specifier -- src/main.rs:9:33 | 9 | fn longest(x: str, y: str) - str { | ---- ---- ^ expected named lifetime parameter | help: this functions return type contains a borrowed value, but the signature does not say whether it is borrowed from x or y help: consider introducing a named lifetime parameter | 9 | fn longesta(x: a str, y: a str) - a str { | 错误说缺少生命周期标注更具体地说是返回类型缺少生命周期参数。正如help文本所说函数的返回类型包含一个借用值但函数签名没有说明这个借用值来自x还是来自y。考虑引入一个命名生命周期参数。再看这个函数fn longest(x: str, y: str) - str { if x.len() y.len() { x } else { y } }很明显这个函数的返回值要么是x要么是y但无法预先知道是哪一个。如果只看这个函数本身两个输入参数x和y的具体生命周期也是未知的。所以与前面的例子不同我们无法通过比较作用域来判断返回的引用是否会一直有效。借用检查器也做不到因为它不知道返回类型的生命周期是与x绑定还是与y绑定。实际上即使返回值是固定的这样写仍然会报错fn longest(x: str, y: str) - str { x }输出error[E0106]: missing lifetime specifier -- src/main.rs:9:33 | 9 | fn longest(x: str, y: str) - str { | ---- ---- ^ expected named lifetime parameter | help: this functions return type contains a borrowed value, but the signature does not say whether it is borrowed from x or y help: consider introducing a named lifetime parameter | 9 | fn longesta(x: a str, y: a str) - a str { | 编译器仍然无法判断因为函数签名没有表达返回类型中的借用值来自哪里。所以这与函数体内的逻辑无关完全与函数签名有关。该怎么改呢可以按照报错信息中的建议来改 help: this functions return type contains a borrowed value, but the signature does not say whether it is borrowed from x or y help: consider introducing a named lifetime parameter | 9 | fn longesta(x: a str, y: a str) - a str { | 既然它让我们添加泛型生命周期参数我们就添加一个fn longesta(x: a str, y: a str) - a str { if x.len() y.len() { x } else { y } }a表示一个名为a的生命周期。x、y和返回类型都使用生命周期a这意味着x、y和返回值的生命周期是相同的。“相同”这个说法并不完全精确因为main中x和y对应值的实际生命周期其实略有不同。这一点我们会在 10.6 生命周期 Pt.2生命周期的语法与例子 中讨论。现在看完整代码fn main() { let string1 String::from(abcd); let string2 xyz; let result longest(string1.as_str(), string2); println!(The longest string is {result}); } fn longesta(x: a str, y: a str) - a str { if x.len() y.len() { x } else { y } }输出The longest string is abcd
RELATED

相关推荐

OpenClaw框架中的Self-Improving技能:AI Agent自主进化技术解析

OpenClaw框架中的Self-Improving技能:AI Agent自主进化技术解析

1. OpenClaw与Self-Improving技能概述OpenClaw作为新一代AI Agent开发框架,其核心价值在于提供了模块化的技能(Skill)体系。Self-Improving正是其中最引人注目的高级技能之一,它使AI Agent具备了持续进化的能力。不同于传统AI模型的静态表现,…

📅 2026/9/16 5:59:01
AI驱动的课程论文写作工具:书匠策AI全解析

AI驱动的课程论文写作工具:书匠策AI全解析

1. 项目概述:AI驱动的课程论文写作革命"书匠策AI"这个工具的出现,彻底改变了传统课程论文的写作方式。作为一名经历过无数次论文折磨的高校教师,我深刻理解学生们在论文写作中面临的三大痛点:选题迷茫、资料混乱、格式灾…

📅 2026/9/16 5:59:01
Spring Boot 3 + Vue 3 地方特产分享社区系统源码 前后端分离实战

Spring Boot 3 + Vue 3 地方特产分享社区系统源码 前后端分离实战

一、项目简介 地方特产分享社区平台是一个基于 Spring Boot 3 Vue 3 前后端分离的社区系统。系统主要面向地方特产爱好者,提供特产浏览、发布、收藏、品鉴笔记撰写、私信交流等功能。系统包含三种角色:普通用户(浏览、发布、互动&#xff09…

📅 2026/9/15 12:55:58
MORE NEWS

更多资讯

📰

2026年Novel售后服务费用包含什么?收费项目与推荐厂家

2026 年,高校、医疗机构及工业研发机构在采购德国 novel 足底压力测量设备后,售后保障成为关注焦点。柔性压力传感与步态分析类精密仪器结构复杂,传感器校准、硬件检修、软件调试均会产生相应成本。本文以广州欧迈志传感科技有限公司为切入主体,梳理 novel 设备免费与付费售后项…

📰

基于AlphaPose与JAAD的行人意图识别:从姿态估计到机器学习落地

简介:面向计算机视觉与自动驾驶场景,这份资源以JAAD行人数据集为基准,包含基于Alpha Pose的姿态识别、行人边界框与姿态结果匹配、SGD/SVM/Random Forest等分类模型训练及多种评价指标实现。代码结构围绕数据处理、模型训练与结果评估展开&am…

📰

PyGame飞机大战实战:游戏循环、Sprite设计与碰撞检测

简介:这是一份面向Python初学者与游戏开发入门者的实战型学习资源,提供完整的‘飞机大战’飞行射击小游戏源码及配套素材,帮助读者通过可运行项目掌握pygame核心机制与面向对象游戏设计思想。压缩包共20个文件,包含5个核心Python源…

📰

agent-skills:可插拔、可版本化的业务能力封装范式

1. 项目概述:一个被严重低估的“技能容器”设计范式“agent-skills”这个词乍看像某个开源库的包名,但真正懂行的人一眼就能看出它背后藏着一套现代软件工程里最务实、也最容易被忽视的架构思想——不是AI Agent的炒作概念,而是可插拔、可复用…

📰

NVSentinel:基于DCGM与Unix socket的GPU健康哨兵系统

1. 项目概述:这不是一个“监控面板”,而是一套嵌入式GPU健康哨兵系统你有没有遇到过这样的情况:训练模型时显卡温度突然飙到92℃,风扇狂转像直升机起飞,但日志里却只有一行模糊的“CUDA error: out of memory”&#x…

📰

100G FPGA UDP上板测试:从物理层到协议栈的全链路验证

1. 项目概述:为什么一个“100G FPGA UDP上板测试”值得花两周时间搭环境、调时序、抓包分析你手头刚拿到一块Xilinx UltraScale VU9P的FPGA开发板,厂商文档里写着“支持100G以太网接口”,但实际连上服务器一跑iperf3,吞吐卡在72Gb…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬