添加到基于 RefCell 构建的二叉树时,借用的值不会存在足够长的时间
Borrowed value does not live long enough when adding to a binary tree built on RefCell
我尝试在二叉树中实现一个add
操作:
use std::cell::RefCell;
use std::cmp::PartialOrd;
type Link<T> = RefCell<Option<Box<Node<T>>>>;
struct Node<T> {
key: T,
left: Link<T>,
right: Link<T>,
}
struct Tree<T> {
root: Link<T>,
}
impl<T> Node<T> {
fn new(val: T) -> Self {
Node {
key: val,
left: RefCell::new(None),
right: RefCell::new(None),
}
}
}
impl<T: PartialOrd> Tree<T> {
fn new() -> Self {
Tree {
root: RefCell::new(None),
}
}
fn add(&self, val: T) {
let mut next = self.root.borrow();
let node = Box::new(Node::new(val));
match next.as_ref() {
None => {
self.root.replace(Some(node));
()
}
Some(root_ref) => {
let mut prev = root_ref;
let mut cur: Option<&Box<Node<T>>> = Some(root_ref);
while let Some(node_ref) = cur {
prev = node_ref;
if node.key < node_ref.key {
next = node_ref.left.borrow();
} else {
next = node_ref.right.borrow();
}
cur = next.as_ref();
}
if node.key < prev.key {
prev.left.replace(Some(node));
} else {
prev.right.replace(Some(node));
}
}
}
}
}
fn main() {}
我不明白为什么 next
变量的寿命不够长:
error[E0597]: `next` does not live long enough
--> src/main.rs:36:15
|
36 | match next.as_ref() {
| ^^^^ borrowed value does not live long enough
...
60 | }
| - `next` dropped here while still borrowed
|
= note: values in a scope are dropped in the opposite order they are created
error[E0597]: `next` does not live long enough
--> src/main.rs:51:27
|
51 | cur = next.as_ref();
| ^^^^ borrowed value does not live long enough
...
60 | }
| - `next` dropped here while still borrowed
|
= note: values in a scope are dropped in the opposite order they are created
next
存在于 add
函数的整个范围内,在我看来,包含对它的引用的其他变量在 next
被删除之前被删除。
编译器说"values in a scope are dropped in the opposite order they are created"
,提示有另一种声明变量的方法可以解决这个问题,但我不知道如何。
我看到的问题是,为了更新树的叶节点,您必须保留对每个中间步骤的引用,而不仅仅是其父节点,因为必须保持到根节点的所有链接都处于活动状态当您更新值时。而 Rust 生命周期无法做到这一点。
也就是说,Rust 不能在循环中做到这一点,但它可以在递归函数中做到这一点,树最好用递归函数实现。
自然地,您的递归结构是 Node
,而不是 Tree
,但是像这样的东西可以工作(有很多方法可以使借用工作):
impl<T: PartialOrd> Node<T> {
fn add(&self, val: T) {
let mut branch = if val < self.key {
self.left.borrow_mut()
} else {
self.right.borrow_mut()
};
if let Some(next) = &*branch {
next.add(val);
return;
}
//Separated from the if let so that branch is not borrowed.
*branch = Some(Box::new(Node::new(val)));
}
}
然后,在 impl Tree
中将工作转交给这一位。
如果像其他人指出的那样,您摆脱了 Tree
与 Node
和 RefCell
...
,代码可能会稍微简化一些
我尝试在二叉树中实现一个add
操作:
use std::cell::RefCell;
use std::cmp::PartialOrd;
type Link<T> = RefCell<Option<Box<Node<T>>>>;
struct Node<T> {
key: T,
left: Link<T>,
right: Link<T>,
}
struct Tree<T> {
root: Link<T>,
}
impl<T> Node<T> {
fn new(val: T) -> Self {
Node {
key: val,
left: RefCell::new(None),
right: RefCell::new(None),
}
}
}
impl<T: PartialOrd> Tree<T> {
fn new() -> Self {
Tree {
root: RefCell::new(None),
}
}
fn add(&self, val: T) {
let mut next = self.root.borrow();
let node = Box::new(Node::new(val));
match next.as_ref() {
None => {
self.root.replace(Some(node));
()
}
Some(root_ref) => {
let mut prev = root_ref;
let mut cur: Option<&Box<Node<T>>> = Some(root_ref);
while let Some(node_ref) = cur {
prev = node_ref;
if node.key < node_ref.key {
next = node_ref.left.borrow();
} else {
next = node_ref.right.borrow();
}
cur = next.as_ref();
}
if node.key < prev.key {
prev.left.replace(Some(node));
} else {
prev.right.replace(Some(node));
}
}
}
}
}
fn main() {}
我不明白为什么 next
变量的寿命不够长:
error[E0597]: `next` does not live long enough
--> src/main.rs:36:15
|
36 | match next.as_ref() {
| ^^^^ borrowed value does not live long enough
...
60 | }
| - `next` dropped here while still borrowed
|
= note: values in a scope are dropped in the opposite order they are created
error[E0597]: `next` does not live long enough
--> src/main.rs:51:27
|
51 | cur = next.as_ref();
| ^^^^ borrowed value does not live long enough
...
60 | }
| - `next` dropped here while still borrowed
|
= note: values in a scope are dropped in the opposite order they are created
next
存在于 add
函数的整个范围内,在我看来,包含对它的引用的其他变量在 next
被删除之前被删除。
编译器说"values in a scope are dropped in the opposite order they are created"
,提示有另一种声明变量的方法可以解决这个问题,但我不知道如何。
我看到的问题是,为了更新树的叶节点,您必须保留对每个中间步骤的引用,而不仅仅是其父节点,因为必须保持到根节点的所有链接都处于活动状态当您更新值时。而 Rust 生命周期无法做到这一点。
也就是说,Rust 不能在循环中做到这一点,但它可以在递归函数中做到这一点,树最好用递归函数实现。
自然地,您的递归结构是 Node
,而不是 Tree
,但是像这样的东西可以工作(有很多方法可以使借用工作):
impl<T: PartialOrd> Node<T> {
fn add(&self, val: T) {
let mut branch = if val < self.key {
self.left.borrow_mut()
} else {
self.right.borrow_mut()
};
if let Some(next) = &*branch {
next.add(val);
return;
}
//Separated from the if let so that branch is not borrowed.
*branch = Some(Box::new(Node::new(val)));
}
}
然后,在 impl Tree
中将工作转交给这一位。
如果像其他人指出的那样,您摆脱了 Tree
与 Node
和 RefCell
...