起因來自於《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)。