关于《C++ Concurrency in Action》中joining_thread传值构造的疑问
关于《C++ Concurrency in Action》中joining_thread构造函数传值的疑问解答
首先明确核心前提:std::thread是不可拷贝的,它的拷贝构造函数被显式删除了,所以你提到的joining_thread jt(t);(t是左值std::thread对象)根本无法通过编译——这不是joining_thread的设计问题,是std::thread本身的特性决定的。
那为什么joining_thread的第二个构造函数要按值传递std::thread?主要有两个原因:
- 简化代码逻辑,兼容多场景:按值传递可以同时处理两种情况:
- 传入临时右值(比如
joining_thread jt{std::thread(fct)};),此时参数会直接通过移动构造创建,不需要额外重载; - 传入显式std::move后的左值线程(比如
std::thread t(fct); joining_thread jt(std::move(t));),此时参数也是通过移动构造生成,再转移到类内部的thread成员中。
全程没有任何拷贝操作,因为std::thread不支持拷贝,所谓的“传值”本质是移动语义的复用。
- 传入临时右值(比如
- 明确所有权转移语义:joining_thread的设计目标是接管线程的所有权,并在自身析构时负责join该线程。按值传递强制调用者明确表达所有权转移的意图——要么传临时对象(天然完成转移),要么显式用std::move交出左值线程的所有权,避免出现“线程被多个对象同时持有”的模糊情况。
而你提到的thread_guard设计不同,是因为它的定位是临时保护已有线程,不接管所有权,只是确保在自身析构时join传入的线程,所以它需要接受左值引用,保持对原线程对象的关联,而不是转移所有权。
你之前的误解在于误以为“按值传递会复制线程”,但实际上std::thread不允许拷贝,这里的传值只是利用了移动语义,最终实现的是线程所有权的安全转移,而非创建副本。
内容的提问来源于stack exchange,提问作者Chenoille
相关产品推荐
相关产品推荐

