为啥 c++ 线程是可移动的但不可复制的?

Posted

技术标签:

【中文标题】为啥 c++ 线程是可移动的但不可复制的?【英文标题】:Why c++ threads are movable but not copiable?为什么 c++ 线程是可移动的但不可复制的? 【发布时间】:2016-01-27 12:11:42 【问题描述】:

正如问题的标题所说,为什么 C++ 线程(std::threadpthread)是可移动但不可复制的?如果我们确实让它可复制,会有什么后果?

【问题讨论】:

那么您希望它做什么?产生一个新线程,对所有相同的数据执行与现有线程相同的功能 真的明智吗?任何尝试使用几乎肯定会出错。 使某些东西可移动但不可复制是一种确保对象只有一个唯一实例的方法。 fstream 类型的工作方式相同,您可以移动它但不能复制它(这样我们就不必决定是否复制也应该在磁盘上创建另一个文件)。 谢谢大家,有没有人愿意提供一个“答案”以便我可以结束这个问题? 【参考方案1】:

关于复制,考虑以下sn-p:

void foo();

std::thread first (foo);     
std::thread second = first; // (*)

当标记为(*) 的行发生时,大概有一些foo 已经执行。那么,预期的行为会是什么?从一开始就执行foo?暂停线程,复制寄存器和状态,然后从那里重新运行?

特别是,鉴于function objects 现在是标准的一部分,通过重用函数对象,很容易启动另一个执行与早期线程完全相同的操作的线程。

因此,开始时没有太多动力。


但是,关于移动,请考虑以下几点:

std::vector<std::thread> threads;

如果没有移动语义,就会出现问题:当向量需要在内部调整大小时,它如何将其元素移动到另一个缓冲区?请参阅此here 的更多信息。

【讨论】:

【参考方案2】:

如果thread 对象是可复制的,那么谁最终负责与thread 对象关联的单线程执行?具体来说,join() 会对每个 thread 对象做什么?

有几种可能的结果,但这就是问题所在,有几种可能的结果没有真正的重叠,可以编码(标准化)为一般用例。

因此,最合理的结果是 1 个执行线程最多与 1 个thread 对象相关联。

这并不是说不能提供某些共享状态,只是用户需要在这方面采取进一步的行动,例如使用std::shared_ptr

【讨论】:

以上是关于为啥 c++ 线程是可移动的但不可复制的?的主要内容,如果未能解决你的问题,请参考以下文章

为啥 C++11 不能将不可复制的仿函数移动到 std::function?

在可移动和不可复制的类上使用移动和交换习语是不是有意义

Initializer-list-构造一个不可复制(但可移动)对象的向量

为啥微不足道的复制/移动可构造性取决于微不足道的可破坏性?

为啥 MicroBatchReader 必须是可序列化的?任务不可序列化错误

为啥 E(dfa) 是可判定语言?