简介
在本实验中,我们将探讨 Rust 中的生命周期概念,以及编译器如何使用它们来确保代码中借用的有效性。生命周期是编译器的一种结构,它决定了变量从创建到销毁的持续时间。虽然生命周期和作用域相关,但它们并不相同。当使用 & 运算符借用一个变量时,借用具有一个由其声明决定的生命周期,并且只要它在出借者被销毁之前结束,它就是有效的。然而,借用的作用域是由引用的使用位置决定的。提供的示例代码演示了生命周期和作用域在实际中的使用方式,每个变量都有自己的生命周期和作用域。
注意:如果实验未指定文件名,你可以使用任何你想要的文件名。例如,你可以使用
main.rs,并通过rustc main.rs &&./main进行编译和运行。
生命周期
生命周期是编译器(更具体地说是其借用检查器)用于确保所有借用有效的一种结构。具体来说,变量的生命周期从创建时开始,到销毁时结束。虽然生命周期和作用域经常一起被提及,但它们并不相同。
例如,当我们通过 & 借用一个变量时,借用的生命周期由其声明位置决定。因此,只要借用在出借者被销毁之前结束,它就是有效的。然而,借用的作用域由引用的使用位置决定。
在下面的示例以及本节的其余部分中,我们将看到生命周期与作用域的关系,以及两者的区别。
// 下面用线条标注了每个变量的创建和销毁,以此表示生命周期。
// `i` 的生命周期最长,因为它的作用域完全包含了 `borrow1` 和 `borrow2`。
// 由于 `borrow1` 和 `borrow2` 不相交,所以它们的持续时间比较无关紧要。
fn main() {
let i = 3; // `i` 的生命周期开始。 ────────────────┐
// │
{ // │
let borrow1 = &i; // `borrow1` 的生命周期开始。 ──┐│
// ││
println!("borrow1: {}", borrow1); // ││
} // `borrow1` 结束。 ─────────────────────────────────┘│
// │
// │
{ // │
let borrow2 = &i; // `borrow2` 的生命周期开始。 ──┐│
// ││
println!("borrow2: {}", borrow2); // ││
} // `borrow2` 结束。 ─────────────────────────────────┘│
// │
} // 生命周期结束。 ─────────────────────────────────────┘
请注意,没有为生命周期标签分配名称或类型。正如我们将看到的,这限制了生命周期的使用方式。
总结
恭喜你!你已经完成了生命周期实验。你可以在 LabEx 中练习更多实验来提升你的技能。