【问题标题】:How to append/copy an STL container object to another object when its value is not copy constructible e.g. std::thread当 STL 容器对象的值不可复制构造时,如何将 STL 容器对象附加/复制到另一个对象,例如标准::线程
【发布时间】:2014-12-18 23:08:29
【问题描述】:

我想移动一个std::map 容器对象到另一个。最简单的形式:

#include<map>
#include<thread>
#include<vector>
using namespace std;

int main ()
{
  map<void*, vector<thread>> m1, m2; 
  // m1 is updated 

  m1.insert(m2.begin(), m2.end());  // <--- problem here
  m2.clear();  // not required anymore
}

但是它给出了error的页面:

error: use of deleted function ‘std::thread::thread(const std::thread&)’

如何做到这一点?

【问题讨论】:

  • 嗯,你不能复制线程。我唯一的建议是map&lt;void*, vector&lt;shared_ptr&lt;thread&gt;&gt;&gt;(或map&lt;void*, shared_ptr&lt;vector&lt;thread&gt;&gt;&gt;,以更合适的为准)。
  • 你所要求的并不真正有意义——复制一个线程是什么意思?你想移动它吗?
  • @Cameron,是的,实际上它是移动的。之后我会运行m2.clear()
  • @iammilind:更好的是,在这种情况下,您可以一次简单地移动整个地图:m1 = std::move(m2);(之后m2 将处于有效但未指定的状态 - 如果您想要将其重新用于其他用途,只需先将其清除即可。)
  • @iammilind:啊,然后选择std::make_move_iterator 答案之一(然后是m2.clear() 以摆脱空对象外壳),这会将项目适当地移动到m1 .

标签: c++ c++11 stl compiler-errors rvalue


【解决方案1】:

std::thread 不可复制,您必须使用允许移动的迭代器:

m1.insert(std::make_move_iterator(m2.begin()),
          std::make_move_iterator(m2.end());

std::make_move_iterator 返回一个专门的迭代器类std::move_iterator,其访问成员(operator*()operator-&gt;())返回对右值的引用,这与返回左值的内置迭代器不同。 map::insert() 将其操作委托给 map::emplace(),在那里它将参数转发到元素类型。

您的线程的复制构造函数被调用,因为从内置迭代器返回的对象被作为 lvalues 转发并因此被复制。

【讨论】:

    【解决方案2】:

    为了完整起见,&lt;algorithm&gt; 中有一个鲜为人知的 std::move 版本,它遵循与 std::copy 类似的模式。

    所以你可以这样写:

    move(begin(m2), end(m2), inserter(m1, begin(m1)));
    m2.clear();
    

    reference here

    【讨论】:

      【解决方案3】:

      使用移动迭代器移动它们:

      m1.insert(make_move_iterator(begin(m2)), make_move_iterator(end(m2)));
      

      【讨论】:

        【解决方案4】:

        我认为您无法插入一系列只能移动的元素。不过,您应该能够std::move() 各个元素:

        for (auto& element: m2) {
            m1.emplace(element.first, std::move(element.second));
        }
        

        【讨论】:

        • 相反,有std::make_move_iterator。但当然,它在语义上与副本不同。
        【解决方案5】:

        一般解决方案:移动它。

        但是,虽然std::move() 可以移动单个值,但它不能移动值范围。您需要编写一个循环:

        for (auto&& pair : m1) m2[pair.first] = std::move(pair.second)
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2013-04-08
          • 2011-08-06
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-03-18
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多