我有以下代码:
struct State<'w> {
surface: &'w u32,
}
impl<'w> State<'w> {
fn new(window: &'w u32) -> State {
State {
surface: window
}
}
}
#[derive(Default)]
struct App<'w> {
state: Option<State<'w>>,
window: Option<u32>,
}
impl<'w> App<'w> {
fn resume(&mut self) {
self.window = Some(1);
let state = State::new(&self.window.as_ref().unwrap());
self.set_state(state);
}
fn set_state(&mut self, state: State<'w>) {
self.state = Some(state);
}
}
fn main()
{
let mut app = App::default();
app.resume();
}
现在我知道这是一个自引用结构。但在我尝试修复它之前,我首先想了解一下附加到参考文献的选项对于一生来说实际上意味着什么?
AI 告诉我这样的事情:
您遇到的错误是由于生命周期 'w App<'w> 结构体的生命周期与 State<'w> 结构中的引用。
但这听起来像是
<'w>
表示整个 App 结构的生命周期,是真的吗?我最初认为 <'w>
只是一个通用参数,告诉编译器“涉及生命周期”,因为在我的书中,生命周期 'w 仅在实例化状态对象时(在对 set_state
的调用中)开始,因为选项以前默认为 None
。该点可能是在应用程序的生命周期开始之后很长一段时间(在main()
中)。我这样的假设是否错误?也许有人可以阐明这一点,这对我作为初学者来说是一个非常令人困惑的话题:)
您收到的错误消息可能是这样的:
error: lifetime may not live long enough
--> <source>:23:9
|
19 | impl<'w> App<'w> {
| -- lifetime `'w` defined here
20 | fn resume(&mut self) {
| - let's call the lifetime of this reference `'1`
...
23 | self.set_state(state);
| ^^^^^^^^^^^^^^^^^^^^^ argument requires that `'1` must outlive `'w`
正如此错误消息明确指出的那样,它指的是
'1
引用的生命周期 &mut self
不如 'w
长。所以,它不需要对我们的 Option
对象做任何事情。对于编译器来说, &self
只是一个引用,它显然与 App
类的生命周期没有固有的联系,所以当你显式地声明它时,错误就会消失:
fn resume(&'w mut self) {
self.window = Some(1);
let state = State::new(&self.window.as_ref().unwrap());
self.set_state(state);
}
但是,编译器会向您显示另一个错误:
error[E0502]: cannot borrow `*self` as mutable because it is also borrowed as immutable
--> <source>:23:9
|
19 | impl<'w> App<'w> {
| -- lifetime `'w` defined here
...
22 | let state = State::new(&self.window.as_ref().unwrap());
| --------------------
| |
| immutable borrow occurs here
| argument requires that `self.window` is borrowed for `'w`
23 | self.set_state(state);
| ^^^^^^^^^^^^^^^^^^^^^ mutable borrow occurs here
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0502`.
ASM generation compiler returned: 1
这是因为你不能同时拥有对同一个对象的不可变引用和可变引用,在本例中为
self
。这样,编译器可以保护您免受竞争条件的影响。实现这项工作的一种可能性是摆脱 set_state
方法:
fn resume(&'w mut self) {
self.window = Some(1);
let state = State::new(&self.window.as_ref().unwrap());
self.state = Some(state);
}
顺便说明一下,
new
结构体的 State
构造函数在本例中是多余的,您可以只使用默认构造函数,如下所示:
let state = State {
surface: &self.window.as_ref().unwrap(),
}
据我了解,
new
构造函数仅在您的参数与结构体的实际成员不同时才有用,例如,如果您想用一个或多个不同类型的对象实例化您的State
.