【问题标题】:Access values in boxed nested struct访问盒装嵌套结构中的值
【发布时间】:2017-12-07 19:44:59
【问题描述】:

我对 Rust 还很陌生,想实现一个 AVL-Tree。

我正在使用以下枚举来表示我的树:

enum AvlTree<T> {
    Leaf,
    Node {
        left: Box<AvlTree<T>>,
        right: Box<AvlTree<T>>,
        value: T
    }
}

在实现其中一项平衡功能时,我在所有权和借款方面遇到了一些问题。

我正在尝试编写一个函数,它接受一个AvlTree&lt;T&gt; 并返回另一个AvlTree&lt;T&gt;。我的第一次尝试是这样的:

fn balance_ll(tree: AvlTree<T>) -> AvlTree<T> {
    if let AvlTree::Node {left: t, right: u, value: v} = tree {
        if let AvlTree::Node {left: ref tl, right: ref ul, value: ref vl} = *t {
            AvlTree::Leaf // Return a new AvlTree here
        } else {
            tree
        }
    } else {
        tree
    }
}

即使是这个最小的例子,编译器也会返回一个错误:

error[E0382]: use of partially moved value: `tree`             
  --> avl.rs:67:17             
   |                           
63 |         if let AvlTree::Node {left: t, right: u, value: v} = tree {                                                       
   |                                     - value moved here    
...                            
67 |                 tree      
   |                 ^^^^ value used here after move           
   |                           
   = note: move occurs because `(tree:AvlTree::Node).left` has type `std::boxed::Box<AvlTree<T>>`, which does not implement the `Copy` trait                  

我认为,我正确理解了错误消息,因为解构 AvlTree::Node 将带走树示例的所有权。我怎样才能防止这种情况发生?我已经尝试了各种方法并(取消)引用tree-变量,只是为了面对更多错误。

此外,我想在新结构中使用一些提取的值,例如 utlvl。这是可能的吗?你能不能提供一个最小的例子来做到这一点?执行该函数后,我不需要访问旧树。

【问题讨论】:

    标签: enums rust avl-tree ownership


    【解决方案1】:

    我认为,我正确理解了错误消息,因为解构 AvlTree::Node 将夺走树示例的所有权。

    是的。如果您之后仍然需要能够使用tree,则需要复制它:

    #[derive(Clone)]
    enum AvlTree<T> {...}
    
    fn balance_ll<T: Clone>(tree: AvlTree<T>) -> AvlTree<T> {
        let copy = tree.clone();
    
        if let AvlTree::Node { left: t, right: u, value: v } = tree {
            if let AvlTree::Node { left: ref tl, right: ref ul, value: ref vl } = *t {
                AvlTree::Leaf // Return a new AvlTree here
            } else {
                copy
            }
        } else {
            tree
        }
    }
    

    或使用快速释放其所有权的辅助函数 - 但我认为没有盒子模式是不可能的:

    #![feature(box_patterns)]
    
    impl<T> AvlTree<T> {
        fn is_left_node(&self) -> bool {
            if let &AvlTree::Node { left: ref t, right: ref u, value: ref v } = self {
                if let &box AvlTree::Node { left: ref tl, right: ref ul, value: ref vl } = t {
                    true
                } else {
                    false
                }
            } else {
                false
            }
        }
    }
    
    fn balance_ll<T>(tree: AvlTree<T>) -> AvlTree<T> {
        if tree.is_left_node() {
            AvlTree::Leaf
        } else {
            tree
        }
    }
    

    由于您可能想使用解构后的值,您可能更喜欢clone 变体,但也许另一个会给您一些额外的想法。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-02-19
      • 1970-01-01
      • 2021-09-15
      • 2021-07-22
      • 2023-03-17
      • 1970-01-01
      相关资源
      最近更新 更多