将消费树转换为非消费树

时间:2015-10-09 01:16:45

标签: rust

我创建了以下具有消耗深度优先遍历的树。

Playpen

struct TreeNode {
    value: i32,
    left: Option<Box<TreeNode>>,
    right: Option<Box<TreeNode>>,
}

fn main() {
    let root = build_tree();
    root.depth_first_pre();
}

fn build_tree() -> TreeNode {
    let root = TreeNode { value: 2,
        left: Some(Box::new(TreeNode { value: 7,
                            left: Some(Box::new(TreeNode { value: 2, left: None, right: None })),
                            right: Some(Box::new(TreeNode { value: 6,
                                                left: Some(Box::new(TreeNode { value: 5, left: None, right: None })),
                                                right: Some(Box::new(TreeNode { value: 11, left: None, right: None })) })) })),
        right: Some(Box::new(TreeNode { value: 5,
                            left: None,
                            right: Some(Box::new(TreeNode { value: 9,
                                                left: Some(Box::new(TreeNode { value: 4, left: None, right: None })),
                                                right: None })) }))};
    return root;
}

impl TreeNode {
    fn depth_first_pre(self) {
        print!("{}, ", self.value);

        if self.left.is_some() {
            self.left.unwrap().depth_first_pre();
        }

        if self.right.is_some() {
            self.right.unwrap().depth_first_pre();
        }
    }
}

Unwrap从该选项中取出值,在这种情况下是正常的,因为每个值只被访问一次。

如果我尝试两次调用该函数,则会出现问题:

root.depth_first_pre();
root.depth_first_pre();

这导致函数的第二次调用出错:

<anon>:10:5: 10:9 error: use of moved value: `root` [E0382]
<anon>:10     root.depth_first_pre();
              ^~~~
<anon>:9:5: 9:9 note: `root` moved here because it has type `TreeNode`, which is non-copyable
<anon>:9     root.depth_first_pre();
             ^~~~
error: aborting due to previous error

我的理解是,它已被第一个函数调用移出,并在该函数超出范围后解除分配。

我如何解决这个问题?

我尝试更改该功能以引用自我(&self)并将.unwrap()更改为as_ref(),但这并未解决我的问题。

1 个答案:

答案 0 :(得分:4)

通过您建议的更改 添加 as_ref,而不是将unwrap替换为as_ref,它可以正常工作:

fn depth_first_pre(&self) {
    print!("{}, ", self.value);

    if self.left.is_some() {
        self.left.as_ref().unwrap().depth_first_pre();
    }

    if self.right.is_some() {
        self.right.as_ref().unwrap().depth_first_pre();
    }
}

但是,使用if let

会更加惯用
fn depth_first_pre(&self) {
    print!("{}, ", self.value);

    if let Some(ref left) = self.left {
       left.depth_first_pre();
    }

    if let Some(ref right) = self.right {
        right.depth_first_pre();
    }
}