起因来自于《C++并发编程实战》的这样一个例子
#include <thread> #include <iostream> #include <stdexcept> class ScropeThread { public: ScropeThread(std::thread t) :m_pThead(std::move(t)) { if (!m_pThead.joinable()) { throw std::logic_error("no thread"); } } ~ScropeThread() { m_pThead.join(); } ScropeThread(const ScropeThread &) = delete; ScropeThread& operator=(const ScropeThread &) = delete; private: std::thread m_pThead; }; void fun(void){} int main() { ScropeThread(std::thread(fun)); return 0; }
我“灵机一动”,将main函数变成了这个亚子:
int main() { std::thread t1(fun); ScropeThread st(t1); return 0; }
编译器毫不犹豫的给我报错了:
一个是先定义了一个thread对象t1,然后用将t1作为参数传入scropethread的构造函数,一个是定义了一个临时的thread对象,然后将其传入scropethread的参数列表。
这两种方法都需要利用拷贝构造函数将实参拷贝给形参,即这两种方法都用到了thread类的拷贝构造函数。
报错的原因用人话来说就是thread类没有定义拷贝构造函数。我百思不得其解。
折腾了快两个小时。突然福至心灵,想到了c++中右值的概念。对哟,以第一种方式将参数传入scropethread的构造函数时,我在参数列表里建立了一个临时的 std::thread(fun),这是一个右值。
而当我在外面这样定义时: std::thread t1(fun);t1是一个左值。
而错误的真正原因是:thread类没有定义以左值作为参数的拷贝构造函数,但却有以右值作为参数的拷贝构造函数。
点进thread类的头文件,果然如此:
从头文件中,我们也可以得出一个结论:thread对象是不能复制(copy)的,只能移动(move)。