在递归数据结构中移动unique_ptr <t>的数组

时间:2015-07-17 18:22:45

标签: c++ recursion move-semantics

尝试编译以下代码会导致以下编译错误:

  

错误C2280:   &#39;的std ::的unique_ptr&GT; ::的unique_ptr(常量   的std ::的unique_ptr&LT; _Ty,性病:: default_delete&LT; _Ty&GT;&GT; &安培;)&#39; :试图   引用已删除的功能

我的理解是数组&#39; m_children&#39;应该是可移动的,因为unique_ptr指向的类型定义了一个移动构造函数。

除非这是由类的递归性质或我忽略的移动语义的某些元素引起的错误?

#include <array>
#include <memory>
#include <iostream>

class OctreeNode{
public:
    OctreeNode(){ };
    OctreeNode(OctreeNode&& other) : m_children(std::move(other.m_children)){};
private:
    std::array<std::unique_ptr<OctreeNode>, 8> m_children;
};

int main(int argc, char* argv[])
{
    OctreeNode T;
    std::cout << "Success!" << std::endl;
    return 0;
}

3 个答案:

答案 0 :(得分:6)

在vs2013中,std::array标题中<array>的定义似乎不包含移动构造函数或移动赋值运算符。

在C ++规则下,这些应该是自动生成的(并且不需要手动定义),但msvc在vs2015之前不包含隐式生成。

答案 1 :(得分:2)

根据错误消息,它不会调用unique_ptr的移动构造函数。相反,它调用它不存在的拷贝构造函数。因此,迭代unique_ptrs并显式调用move构造函数。

    int i = 0;
    for(auto& x : other.m_children)
        m_children[i++] = std::move(x);

顺便说一下,通常它应该可以工作,因为当且仅当它存储的元素也可以移动时,std :: array是可移动的。在你的情况下,unique_ptr是可移动的,所以它不应该是问题。有关更详细的讨论,请参阅以下链接

Is std::array movable?

答案 2 :(得分:0)

如果存在副本等价物,或者我错了,我不相信std :: array会有编译器生成的移动操作吗?

作为旁注,要移动那些unique_ptrs,可以使用std :: move算法而不是raw循环:

std::move(std::begin(other.m_children), std::end(other.m_children), std::begin(m_children));