我正在尝试定义一个递归结构,类似于用于树遍历的链表。节点包含一些数据和对其父节点的访问权限。子节点应该通过可变引用借用其父节点以确保独占访问,并在其被删除时释放它。我可以使用不可变引用来定义这个结构,但是当我使父引用可变时,我被编译器错误所困扰,无法理解它。
如何为具有可变父引用的这种递归结构定义生命周期?
以下是一个最简示例。这个示例编译成功,但使用了只读引用:
但是我遇到了以下错误:
如何为具有可变父引用的这种递归结构定义生命周期?
以下是一个最简示例。这个示例编译成功,但使用了只读引用:
struct Node<'a> {
// Parent reference. `None` indicates a root node.
// I want this to be a mutable reference.
pub parent: Option<&'a Node<'a>>,
// This field just represents some data attached to this node.
pub value: u32,
}
// Creates a root node
// I use a static lifetime since there's no parent for the root so there are no constraints there
fn root_node(value: u32) -> Node<'static> {
Node {
parent: None,
value,
}
}
// Creates a child node
// The lifetimes indicates that the parent must outlive its child
fn child_node<'inner, 'outer: 'inner>(
parent: &'inner mut Node<'outer>,
value: u32,
) -> Node<'inner> {
Node {
parent: Some(parent),
value,
}
}
// An example function using the struct
fn main() {
let mut root = root_node(0);
let mut c1 = child_node(&mut root, 1);
let mut c2 = child_node(&mut c1, 2);
{
let mut c3 = child_node(&mut c2, 3);
let c4 = child_node(&mut c3, 4);
let mut cur = Some(&c4);
while let Some(n) = cur {
println!("{}", n.value);
cur = n.parent;
}
}
{
let c5 = child_node(&mut c2, 5);
let mut cur = Some(&c5);
while let Some(n) = cur {
println!("{}", n.value);
cur = n.parent;
}
}
println!("{}", c2.value);
}
我想要一个可变引用,所以我尝试将 Node
结构体替换为使用可变引用:
struct Node<'a> {
// Parent reference. `None` indicates a root node.
// I want this to be a mutable reference.
pub parent: Option<&'a mut Node<'a>>,
// This field just represents some data attached to this node.
pub value: u32,
}
但是我遇到了以下错误:
error[E0623]: lifetime mismatch
--> src/main.rs:25:22
|
21 | parent: &'inner mut Node<'outer>,
| ------------------------
| |
| these two types are declared with different lifetimes...
...
25 | parent: Some(parent),
| ^^^^^^ ...but data from `parent` flows into `parent` here
我不理解可变性和数据流入字段之间的关系。在不可变情况下,我已经要求函数传递可变/独占引用。我一直在尝试各种生命周期的组合(使用单个生命周期,反转它们的关系等),但都没有成功。
head.next.next
和(head.next).next
)。 - Shepmasterc3
,它就借用了c2
(以及其中的c1
和root
),因此在c2
被丢弃之前,您无法访问它们,因此不应该能够为它们创建别名(至少这是目标)。 - Demurgos