为什么接受 Box<MyType> 的函数会出现这种情况?抱怨当接受 self 的函数工作时移动的值? [英] Why does a function that accepts a Box<MyType> complain of a value being moved when a function that accepts self works?

查看:60
本文介绍了为什么接受 Box<MyType> 的函数会出现这种情况?抱怨当接受 self 的函数工作时移动的值?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下编译代码:

pub mod Btree {
    pub struct node {
        pub id: u32,
        pub red: bool,
        pub left: Option<Box<node>>,
        pub right: Option<Box<node>>,
    }

    impl<'a> node {
        pub fn insert(mut node_: Option<Box<node>>, id: u32) -> Option<Box<node>> {
            match node_ {
                None => Some(Box::new(node {
                    id: id,
                    red: true,
                    left: None,
                    right: None,
                })),
                Some(x) => x.insert_(id),
            }
        }

        pub fn insert_(mut self, id: u32) -> Option<Box<node>> {
            self.left = node::insert(self.left, id);
            Some(Box::new(self))
        }
    }
}

当我更改 insert_() 以使用 Box 代替时:

When I change insert_() to work with a Box<node> instead:

pub mod Btree {
    pub struct node {
        pub id: u32,
        pub red: bool,
        pub left: Option<Box<node>>,
        pub right: Option<Box<node>>,
    }

    impl<'a> node {
        pub fn insert(mut node_: Option<Box<node>>, id: u32) -> Option<Box<node>> {
            match node_ {
                None => Some(Box::new(node {
                    id: id,
                    red: true,
                    left: None,
                    right: None,
                })),
                Some(x) => node::insert_(x, id),
            }
        }

        pub fn insert_(mut node_: Box<node>, id: u32) -> Option<Box<node>> {
            node_.left = node::insert(node_.left, id);
            Some(node_)
        }
    }
}

我明白了:

error[E0382]: use of partially moved value: `node_`
  --> src/main.rs:23:13
   |
23 |             node_.left = node::insert(node_.left, id);
   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^----------^^^^^
   |             |                         |
   |             |                         value moved here
   |             value used here after move
   |
   = note: move occurs because `node_.left` has type `std::option::Option<std::boxed::Box<Btree::node>>`, which does not implement the `Copy` trait

我不明白那是什么.代码非常相似,两种情况都有一个移动.

I don't understand what that is. The code is very similar and in both cases there is a move.

推荐答案

如果您拥有结构本身,则您只能解构结构(将非Copy 元素移出其中).拥有指向堆上结构的指针是不够的,即使它是一个拥有指针(例如 Box).Shepmaster 的回答更详细地描述了为什么会这样.

You can only destructure a struct (move non-Copy elements out of it) if you have the struct itself in hand. Having a pointer to the struct on the heap is not sufficient, even if it's an owning pointer (e.g. Box). Shepmaster's answer describes in more detail why this is the case.

幸运的是,node.left 是一个 Option<_>,因此有一个简单的解决方法:Option::take..take()Option 上给你内部值(如果有的话),但不消耗 Option,把 代替.所以你可以在调用Node::insert时使用.take()临时交换None,然后用返回值替换它.

Fortunately, node.left is an Option<_>, so there is an easy fix for this: Option::take. .take() on an Option gives you the internal value (if there is one), but without consuming the Option, putting None in its place. So you can use .take() to swap None in temporarily while calling Node::insert, and then replace it with the return value.

pub mod btree {
    pub struct Node {
        pub id: u32,
        pub red: bool,
        pub left: Option<Box<Node>>,
        pub right: Option<Box<Node>>,
    }

    impl Node {
        pub fn insert(node: Option<Box<Node>>, id: u32) -> Option<Box<Node>> {
            match node {
                None => Some(Box::new(Node {
                    id: id,
                    red: true,
                    left: None,
                    right: None,
                })),
                Some(x) => Node::insert_(x, id),
            }
        }

        pub fn insert_(mut node: Box<Node>, id: u32) -> Option<Box<Node>> {
            node.left = Node::insert(node.left.take(), id);
            Some(node)
        }
    }
}

游乐场.

(我重命名了 BtreeNode 以遵循 Rust 命名约定并删除了 <'a> 生命周期.)

(I have renamed Btree and Node to follow Rust naming conventions and removed the <'a> lifetime.)

这篇关于为什么接受 Box&lt;MyType&gt; 的函数会出现这种情况?抱怨当接受 self 的函数工作时移动的值?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆