上一篇教程介绍了从零学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
,分别对应 title
和author
引用。get_title
方法只接收&self
,因此不需要额外的生命周期标注。而 compare_author
方法接收一个额外的引用参数 other_author
,所以需要显式地标注生命周期 'c
。
总结
当函数接收引用作为参数,但是没有返回引用类型时,通常不需要显式标注生命周期,如果函数返回引用或者存储引用,显式标注生命周期可以更好保证内存安全。