Reference 在编写二元搜索树时,参数类型'T'的有效期可能不够长

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> {

我试图在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> {
        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() {
}