用于安全引用的生命周期
深入了解生命周期这一 Rust 机制,掌握它如何确保引用始终有效,并在编译时防止悬空指针。
用于安全引用的生命周期 是 CoddyKit 上的免费 Learn Rust Coding 课时。 这是第 3 节课,共 3 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Learn Rust Coding 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Learn Rust Coding 课程共包含 3 节课。
为什么生命周期很重要
Rust 的所有权和借用规则可以防止许多常见的内存错误。但 Rust 还有另一层安全保障:lifetime。
lifetime 确保代码中的引用始终指向有效数据。它们解决了悬空引用的问题,即引用可能指向已经释放的内存。
悬空指针的风险
设想这样一种情况:函数创建数据,返回指向该数据的引用,然后函数结束时数据被销毁。此时,返回的引用就会指向无效的内存。
Rust 使用 lifetime 在编译时防止这种情况。它会检查您使用的每个引用在您需要它的整个期间是否保持有效,从而确保内存安全。
Rust 推断生命周期
您不必总是手动编写明确的生命周期注解。Rust 有一套生命周期省略规则,允许编译器在常见模式下推断 lifetime。
例如,在只有一个输入引用的函数中,该引用的 lifetime 通常会自动赋予输出引用。这样可以让代码更加简洁!
何时添加注解
当 Rust 无法推断 lifetime 时,您必须明确添加注解。这会告诉编译器不同引用的 lifetime 之间有什么关系。
生命周期注解的语法是一个撇号后跟一个小写字母,例如 'a。它是 lifetime 的泛型参数,而不是表示某个具体时长。
函数的生命周期参数
当函数接收多个引用并返回其中一个引用时,Rust 需要知道输出引用应采用哪个输入引用的 lifetime。这样可以确保返回的引用始终有效。
<'a> 语法声明了一个泛型 lifetime 参数。让我们看一个例子:
fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
if x.len() > y.len() {
x
} else {
y
}
}
fn main() {
let string1 = String::from("abcd");
let string2 = "xyz";
let result = longest(string1.as_str(), string2);
println!("The longest string is: {}", result);
}“'static”生命周期
'static lifetime 是一种特殊情况。它表示引用可以在整个程序运行期间存活。
字符串字面量(例如 "hello world")具有 'static lifetime,因为它们直接存储在程序的二进制文件中,并且在整个执行过程中都可用。
fn main() {
// 'static lifetime for a string literal
let s: &'static str = "I live for the entire program!";
println!("{}", s);
// This is also implicitly 'static
let another_s = "Hello from static land!";
println!("{}", another_s);
}保存引用的结构体
如果结构体保存了引用,您需要在结构体定义中添加生命周期注解。这样可以确保结构体的任何实例都不会超过其引用所指向数据的存活时间。
结构体的 lifetime 参数告诉 Rust,其中的所有引用都必须至少具有该 lifetime。
struct ImportantExcerpt<'a> {
part: &'a str,
}
fn main() {
let novel = String::from("Call me Ishmael. Some years ago...");
let first_sentence = novel.split('.').next().expect("Could not find a '.'");
let i = ImportantExcerpt {
part: first_sentence,
};
println!("Excerpt part: {}", i.part);
}生命周期与泛型
lifetime 也是泛型的一种形式!您可以将 lifetime 与类型泛型结合起来,创建灵活且安全的数据结构或函数。
例如,结构体可以保存指向泛型类型的引用,并让这些引用都受到同一个 lifetime 参数的约束,从而确保复杂的数据关系始终有效。
解读编译器错误
第一次遇到 lifetime 错误时,您可能会觉得它们令人畏惧。最常见的错误是“借用可能存活时间不够长”。
这通常意味着您试图在引用所指向的数据被释放后继续使用该引用,或者 Rust 无法证明该引用有效。理解这些提示信息可以帮助您调整生命周期注解。
快速检查:生命周期
下面哪一项最准确地描述了 Rust 的显式生命周期注解旨在解决的核心问题?
生命周期:编译时安全
您已经了解到,lifetime 是 Rust 内存安全保证的重要组成部分。它们通过确保所有引用在整个使用期间都有效,来防止悬空引用。
- Rust 通常使用省略规则推断 lifetime。
- 无法推断时,您可以使用类似
'a的显式注解。 - 对于返回引用的函数和保存引用的结构体,lifetime 至关重要。
- 特殊的
'staticlifetime 会持续整个程序运行期间。
掌握 lifetime 是编写健壮 Rust 代码的关键!
常见问题解答
「用于安全引用的生命周期」课时是免费的吗?
是的 — 「用于安全引用的生命周期」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Learn Rust Coding 课程的其余内容,请升级到 CoddyKit PRO。 Learn Rust Coding 课程共包含 3 节课。
「用于安全引用的生命周期」这节课中我会学到什么?
深入了解生命周期这一 Rust 机制,掌握它如何确保引用始终有效,并在编译时防止悬空指针。 你通过在浏览器中直接运行的动手代码来练习 Learn Rust Coding,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 Learn Rust Coding 需要有经验吗?
无需任何先前经验。CoddyKit 上的 Learn Rust Coding 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 3 节课,共 3 节。
「用于安全引用的生命周期」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 Learn Rust Coding 课中编写并运行代码吗?
能。每节 Learn Rust Coding 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。
此课程中的所有课时
- 理解 Rust 的所有权模型
- 详解引用与借用
- 用于安全引用的生命周期