我正在通过显式注释函数签名来测试在Rust中的生命周期理解,并创建了一个我不确定是否理解的示例。
在这个示例中,我模拟了共享一本书并翻页的概念。为此,我使用了一个可变引用,将其传递给一个borrow_and_read
函数,该函数更新Book
结构体的curr_page
字段。我的Book
结构体和main
函数如下:
#[derive(Debug)]
pub struct Book<'a> {
pub title: &'a str,
pub curr_page: Option<i32>,
pub page_count: i32,
}
fn borrow_and_read<'a>(a_book: &'a mut Book<'a>) {
match a_book.curr_page {
Some(page) => a_book.curr_page = Some(page + 1),
None => a_book.curr_page = Some(0),
};
}
fn main() {
let mut the_book: Book = Book {
title: "The Book",
curr_page: None,
page_count: 104,
};
let a_book: &mut Book = &mut the_book;
borrow_and_read(a_book);
borrow_and_read(a_book);
observe_book(&*a_book);
}
pub fn observe_book<'a>(a_book: &'a Book<'a>) {
println!("Observing: {:?}", a_book);
}
在我第一次实现borrow_and_read函数时,我让编译器添加注释,所有内容都编译成功了:
fn borrow_and_read(a_book: &mut Book) {
match a_book.curr_page {
Some(page) => a_book.curr_page = Some(page + 1),
None => a_book.curr_page = Some(0),
};
}
我接着尝试添加单个生命周期注释,为引用和 Book
实例指定一个生命周期:
fn borrow_and_read<'a>(a_book: &'a mut Book<'a>) {
match a_book.curr_page {
Some(page) => a_book.curr_page = Some(page + 1),
None => a_book.curr_page = Some(0),
};
}
这导致了以下错误:
error[E0499]: cannot borrow `*a_book` as mutable more than once at a time
--> src/main.rs:25:21
|
24 | borrow_and_read(a_book);
| ------ first mutable borrow occurs here
25 | borrow_and_read(a_book);
| ^^^^^^
| |
| second mutable borrow occurs here
| first borrow later used here
error[E0502]: cannot borrow `*a_book` as immutable because it is also borrowed as mutable
--> src/main.rs:27:18
|
24 | borrow_and_read(a_book);
| ------ mutable borrow occurs here
...
27 | observe_book(&*a_book);
| ^^^^^^^^
| |
| immutable borrow occurs here
| mutable borrow later used here
在仔细思考了我最初尝试的方法后,我决定将可变引用
Book
的生命周期与Book
实例本身的生命周期分开。然后我想到下面这个方案:fn borrow_and_read<'a, 'b>(a_book: &'a mut Book<'b>)
where 'b : 'a {
match a_book.curr_page {
Some(page) => a_book.curr_page = Some(page + 1),
None => a_book.curr_page = Some(0),
};
}
这段代码确实可以编译并输出预期的结果。
我对于为什么最初报错提示a_book
被借用了多次感到困惑。我原以为只要传递一个可变引用就可以了,因为每个使用该引用的地方都知道这个引用是可变的。我的想法似乎在borrow_and_read
函数的最终实现中得到了确认,但我不完全确定为什么通过使用where 'b : 'a
指定Book
实例的生命周期超出可变引用范围可以解决我的问题。
我希望能够深入理解为什么将同样的生命周期用于可变引用和Book
实例会导致错误。
borrow_and_read
之间被丢弃了?我感到困惑,因为我使用的是一个单一的引用,在主函数中创建,我认为它在整个主函数的生命周期内都存在。我知道不包括生命周期注释也能得到一个工作的程序,但我希望能更好地理解 - 不仅仅是让程序正常运行。 - AC-5