【问题标题】:Moving array of unique_ptr<T> in a recursive data structure在递归数据结构中移动 unique_ptr<T> 数组
【发布时间】:2015-10-07 13:23:45
【问题描述】:

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

错误 C2280: 'std::unique_ptr>::unique_ptr(const std::unique_ptr<_ty>> &)' :试图 引用已删除的函数

我的理解是数组 'm_children' 应该是可移动的,因为 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;
}

【问题讨论】:

  • 在 clang 和 gcc 中编译。
  • 您使用的是什么编译器以及哪些编译选项?
  • 您可以将示例 main 缩减为 struct SomeStruct{}; std::array&lt;std::unique_ptr&lt;SomeStruct&gt;, 1&gt; foo, bar; foo = std::move(bar);
  • @Nathan Oliver msvc,视觉工作室 2013。
  • 我没有 VS 2013,但它可以在 VS2015 上编译。你有 CTP2 吗?

标签: c++ recursion move-semantics


【解决方案1】:

似乎在 vs2013 中,&lt;array&gt; 标头中 std::array 的定义不包含移动构造函数或移动赋值运算符。

根据 C++ 规则,这些应该是自动生成的(因此不需要手动定义),但 msvc 直到 vs2015 才包括隐式生成。

【讨论】:

    【解决方案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?

    【讨论】:

      【解决方案3】:

      如果存在复制等价物,我不相信 std::array 会有编译器生成的移动操作,还是我错了?

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

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

      【讨论】:

        猜你喜欢
        • 2018-08-27
        • 1970-01-01
        • 2015-02-19
        • 1970-01-01
        • 2017-01-18
        • 1970-01-01
        • 2017-08-06
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多