上一篇教程介绍了从零学Rust第二章-所有权,引用和借用,这次来说下 rust 的生命周期,生命周期也是 rust 为了内存安全而引入的概念。

概念

rust 用生命周期来描述引用在程序的有效范围。每个引用都有一个生命周期,它定义了该引用从何时开始有效,到何时失效。生命周期的主要目的是防止悬空引用 (dangling references)和数据竞争(data races),从而确保内存安全。

标注

rust 生命周期标注通过手动显示标注,使用标注符 ' 说明引用的有效范围,举个例子

fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
if x.len() > y.len() {
x
} else {
y
}
}

这里的  <'a>  是泛型生命周期参数声明,表明函数中涉及引用的生命周期会用  'a  这个生命周期来管理。函数的参数  x  和  y  和函数的返回值 str 的生命周期都为  'a

多个生命周期标注

fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
if x.len() > y.len() {
x
} else {
y
}
}

这里的  <'a>  是泛型生命周期参数声明,表明函数中涉及引用的生命周期会用  'a  这个生命周期来管理。函数的参数  x  和  y  和函数的返回值的生命周期都为  'a

生命周期和结构体

在结构体中使用生命周期标注,可以确保结构体中的引用在结构体的生命周期内有效。

为了更好理解,我们来看一个比较复杂的代码例子:

struct Book<'a, 'b> {
title: &'a str,
author: &'b str,
}
impl<'a, 'b> Book<'a, 'b> {
// 这个方法只接收 &self,所以不需要额外的生命周期标注
fn get_title(&self) -> &'a str {
self.title
}
// 这个方法接收一个额外的引用参数,需要显式标注生命周期
fn compare_author<'c>(&self, other_author: &'c str) -> bool {
self.author == other_author
}
}
fn main() {
let book_title = String::from("Kelen.cc");
let book_author = String::from("Kelen");
let book = Book {
title: &book_title,
author: &book_author,
};
println!("书名: {}", book.get_title());
println!("作者是Kelen吗? {}", book.compare_author("Kelen"));
}

Book 结构体有两个生命周期参数 'a'b,分别对应 titleauthor 引用。get_title方法只接收&self,因此不需要额外的生命周期标注。而 compare_author 方法接收一个额外的引用参数 other_author,所以需要显式地标注生命周期 'c

总结

当函数接收引用作为参数,但是没有返回引用类型时,通常不需要显式标注生命周期,如果函数返回引用或者存储引用,显式标注生命周期可以更好保证内存安全。