Reference 在编写二元搜索树时,参数类型'T'的有效期可能不够长
我试图在Rust中编写一个二元搜索树,但我不明白发生了什么:Reference 在编写二元搜索树时,参数类型'T'的有效期可能不够长,reference,rust,binary-search-tree,lifetime-scoping,Reference,Rust,Binary Search Tree,Lifetime Scoping,我试图在Rust中编写一个二元搜索树,但我不明白发生了什么: enum BST<'a, T: Ord> { Leaf, BinTree { value: T, left: &'a mut BST<'a, T>, right: &'a mut BST<'a, T> } } impl<'a, T: Ord> BST<'a, T> { fn new() -> BST<'a, T> {
enum BST<'a, T: Ord> {
Leaf,
BinTree { value: T, left: &'a mut BST<'a, T>, right: &'a mut BST<'a, T> }
}
impl<'a, T: Ord> BST<'a, T> {
fn new() -> BST<'a, T> {
BST::Leaf
}
fn add(self, val: T) {
match self {
BST::Leaf => self = BST::BinTree {
value: val,
left: &mut BST::<'a, T>::new(),
right: &mut BST::<'a, T>::new()
},
BST::BinTree{value: v, left: l, right: r} => if val < v {
l.add(val);
} else {
r.add(val);
}
}
}
}
fn main() {
}
enum BST BST{
叶
}
fn添加(自身,val:T){
匹配自我{
BST::Leaf=>self=BST::BinTree{
值:val,
左:&mut BST:::新建()
},
BST::BinTree{value:v,left:l,right:r}=>如果val
当我试图编译此文件时,会出现以下错误:
error[E0309]:参数类型'T'的有效期可能不够长
-->堆。rs:3:25
|
3 | BinTree{value:T,left:&'a mut BST`不超过它所指向的数据
-->堆。rs:3:25
|
3 | BinTree{值:T,左:&'a mut BST{
fn new()->BST::new()as&'a mut BST::new()as&'a mut BST::new()as&'a mut BST::new()as&'a mut BST::new()as&'a mut BST heap.rs:15:28
|
15 | fn添加(&mut self,val:T){
| ____________________________^
16 | |匹配*自我{
17 | | BST::Leaf=>*self=BST::BinTree{
18 | |值:val,
... |
27 | | }
28 | | }
| |__^
错误:借用值的有效期不够长
-->堆。rs:20:17
|
20 |右:&mut BST::heap.rs:15:28
|
15 | fn添加(&mut self,val:T){
| ____________________________^
16 | |匹配*自我{
17 | | BST::Leaf=>*self=BST::BinTree{
18 | |值:val,
... |
27 | | }
28 | | }
| |__^
错误:由于之前的两个错误而中止
我知道这可以通过使用
Box
es而不是引用来修复,但我想这样做是为了练习。正如错误消息所说,可以通过添加一个生命周期限制的T:'a
,来修复特定错误。但是,您将得到许多其他错误,因为您尝试执行的操作是不可靠的:您正在尝试存储re对其他地方没有所有者的对象的引用
当您执行诸如存储&mut BST:::new()
之类的操作时,会返回一个将很快被销毁的临时值,因此您无法存储对它的引用并期望它继续存在
您需要节点拥有其子节点而不是引用。您可以通过将子类型更改为left:Box
,并在创建新的子节点时使用Box::new
来实现这一点。一旦这样做,您就可以消除所有的'a
,并且不会出现与生存期相关的错误
另一个问题是,您的
add
消耗了self
参数,因此调用者将无法再使用它。您应该改为使用&mut self
,以便它可以修改调用者拥有的树。您是否尝试过在t
和Ord
旁边放置一个绑定的+a
例如,你试过做编译器所建议的吗?考虑添加一个明确的生命界<代码> T:“A < /代码>?如果没有,为什么?如果你这样做了,你有什么问题吗?也有。你应该阅读它们,因为有人已经花了时间来回答它们。告诉我们什么不起作用。在此之后,感谢您的解释并通知我有关self
的错误。但正如我所说的,我希望通过引用进行练习。@DimoChanev我理解这一点,但正如我所解释的,这是不可能的,因为节点没有所有者。
enum BST<'a, T: Ord + 'a> {
Leaf,
BinTree {
value: T,
left: &'a mut BST<'a, T>,
right: &'a mut BST<'a, T>
}
}
impl<'a, T: Ord + 'a > BST<'a, T> {
fn new() -> BST<'a, T> {
BST::Leaf
}
fn add(&mut self, val: T) {
match *self {
BST::Leaf => *self = BST::BinTree {
value: val,
left: &mut BST::<'a, T>::new() as &'a mut BST<'a, T>,
right: &mut BST::<'a, T>::new() as &'a mut BST<'a, T>
},
BST::BinTree{value: ref v, left: ref mut l, right: ref mut r} => if val < *v {
l.add(val);
} else {
r.add(val);
}
}
}
}
fn main() {
}