递归类型——生命周期问题
Recursive type - lifetime issues
我想我部分理解生命周期概念,但我在递归类型定义中遇到问题:
struct Person<'a> {
name: String,
children: Vec<&'a mut Person<'a>>,
birth: String,
death: String,
religion: String,
genre: String,
}
impl Person<'_> {
fn add_children(&'_ mut self, p: &'_ mut Person<'_>) {
self.children.push(p);
}
}
编译器说:
error[E0312]: lifetime of reference outlives lifetime of borrowed content...
--> src/lib.rs:12:28
|
12 | self.children.push(p);
| ^
|
note: ...the reference is valid for the lifetime `'_` as defined on the impl at 10:13...
--> src/lib.rs:10:13
|
10 | impl Person<'_> {
| ^^
note: ...but the borrowed content is only valid for the anonymous lifetime #2 defined on the method body at 11:5
--> src/lib.rs:11:5
|
11 | fn add_children(&'_ mut self, p: &'_ mut Person<'_>) {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0308]: mismatched types
--> src/lib.rs:12:28
|
12 | self.children.push(p);
| ^ lifetime mismatch
|
= note: expected mutable reference `&mut Person<'_>`
found mutable reference `&mut Person<'_>`
note: the anonymous lifetime #3 defined on the method body at 11:5...
--> src/lib.rs:11:5
|
11 | fn add_children(&'_ mut self, p: &'_ mut Person<'_>) {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...does not necessarily outlive the lifetime `'_` as defined on the impl at 10:13
--> src/lib.rs:10:13
|
10 | impl Person<'_> {
| ^^
error[E0308]: mismatched types
--> src/lib.rs:12:28
|
12 | self.children.push(p);
| ^ lifetime mismatch
|
= note: expected mutable reference `&mut Person<'_>`
found mutable reference `&mut Person<'_>`
note: the lifetime `'_` as defined on the impl at 10:13...
--> src/lib.rs:10:13
|
10 | impl Person<'_> {
| ^^
note: ...does not necessarily outlive the anonymous lifetime #3 defined on the method body at 11:5
--> src/lib.rs:11:5
|
11 | fn add_children(&'_ mut self, p: &'_ mut Person<'_>) {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
怎么样?据我了解,self
和 p
具有相同的生命周期。
我希望它是 Vec<&mut Person>
,因为我有一个 HashMap<String, Person>
,每个人都将其 children 初始化为 Vec::new()
。我想传递对 Vec
的引用,这样它在更新 children.
时不会复制整个人的数据
'_
告诉编译器为您推断生命周期,但在这种情况下,它是在推断一堆不同的匿名生命周期。由于 Person
的生命周期直接取决于其 children
的生命周期,因此您应该在实现中明确说明这一点,并且一旦执行编译:
struct Person<'a> {
name: String,
children: Vec<&'a mut Person<'a>>,
birth: String,
death: String,
religion: String,
genre: String,
}
impl<'a> Person<'a> {
fn add_children(&mut self, p: &'a mut Person<'a>) {
self.children.push(p);
}
}
虽然上面的编译在实践中你会发现它的限制令人难以置信并且难以使用,但如果可以克隆 Person
s 你会更容易使用这个结构相反:
struct Person {
children: Vec<Person>,
// other fields
}
如果您需要在多个children
向量之间共享Person
s同时能够改变它们,您应该选择:
struct Person {
children: Vec<Rc<RefCell<Person>>>,
// other fields
}
如果您将所有 Person
存储在一个 HashMap<String, Person>
中,其中键是唯一且不可变的,您还可以像这样维护每个 children
向量:
struct Person {
children: Vec<String>, // keys for HashMap<String, Person>
// other fields
}
我想我部分理解生命周期概念,但我在递归类型定义中遇到问题:
struct Person<'a> {
name: String,
children: Vec<&'a mut Person<'a>>,
birth: String,
death: String,
religion: String,
genre: String,
}
impl Person<'_> {
fn add_children(&'_ mut self, p: &'_ mut Person<'_>) {
self.children.push(p);
}
}
编译器说:
error[E0312]: lifetime of reference outlives lifetime of borrowed content...
--> src/lib.rs:12:28
|
12 | self.children.push(p);
| ^
|
note: ...the reference is valid for the lifetime `'_` as defined on the impl at 10:13...
--> src/lib.rs:10:13
|
10 | impl Person<'_> {
| ^^
note: ...but the borrowed content is only valid for the anonymous lifetime #2 defined on the method body at 11:5
--> src/lib.rs:11:5
|
11 | fn add_children(&'_ mut self, p: &'_ mut Person<'_>) {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0308]: mismatched types
--> src/lib.rs:12:28
|
12 | self.children.push(p);
| ^ lifetime mismatch
|
= note: expected mutable reference `&mut Person<'_>`
found mutable reference `&mut Person<'_>`
note: the anonymous lifetime #3 defined on the method body at 11:5...
--> src/lib.rs:11:5
|
11 | fn add_children(&'_ mut self, p: &'_ mut Person<'_>) {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...does not necessarily outlive the lifetime `'_` as defined on the impl at 10:13
--> src/lib.rs:10:13
|
10 | impl Person<'_> {
| ^^
error[E0308]: mismatched types
--> src/lib.rs:12:28
|
12 | self.children.push(p);
| ^ lifetime mismatch
|
= note: expected mutable reference `&mut Person<'_>`
found mutable reference `&mut Person<'_>`
note: the lifetime `'_` as defined on the impl at 10:13...
--> src/lib.rs:10:13
|
10 | impl Person<'_> {
| ^^
note: ...does not necessarily outlive the anonymous lifetime #3 defined on the method body at 11:5
--> src/lib.rs:11:5
|
11 | fn add_children(&'_ mut self, p: &'_ mut Person<'_>) {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
怎么样?据我了解,self
和 p
具有相同的生命周期。
我希望它是 Vec<&mut Person>
,因为我有一个 HashMap<String, Person>
,每个人都将其 children 初始化为 Vec::new()
。我想传递对 Vec
的引用,这样它在更新 children.
'_
告诉编译器为您推断生命周期,但在这种情况下,它是在推断一堆不同的匿名生命周期。由于 Person
的生命周期直接取决于其 children
的生命周期,因此您应该在实现中明确说明这一点,并且一旦执行编译:
struct Person<'a> {
name: String,
children: Vec<&'a mut Person<'a>>,
birth: String,
death: String,
religion: String,
genre: String,
}
impl<'a> Person<'a> {
fn add_children(&mut self, p: &'a mut Person<'a>) {
self.children.push(p);
}
}
虽然上面的编译在实践中你会发现它的限制令人难以置信并且难以使用,但如果可以克隆 Person
s 你会更容易使用这个结构相反:
struct Person {
children: Vec<Person>,
// other fields
}
如果您需要在多个children
向量之间共享Person
s同时能够改变它们,您应该选择:
struct Person {
children: Vec<Rc<RefCell<Person>>>,
// other fields
}
如果您将所有 Person
存储在一个 HashMap<String, Person>
中,其中键是唯一且不可变的,您还可以像这样维护每个 children
向量:
struct Person {
children: Vec<String>, // keys for HashMap<String, Person>
// other fields
}