【引例】
#include <iostream>#include <string>#include <thread>using namespace std;void myprint(const int& i, char* pmybuf ) {cout << i << endl;cout << pmybuf << endl;return;}int main(){int val = 1;int& val_y = val;char buf[] = "This is a Test!";thread mythread(myprint, val, buf); mythread.join();std::cout << "主線程收尾" << std::endl;return 0;}要避免的陷阱(解釋1)void myprint(const int i, const string & pmybuf ) {
cout << i << endl;
cout << pmybuf.c_str() << endl;
return;
}
要避免的陷阱(解釋2)thread mythread(myprint, val, buf); //傳遞參數
thread mythread(myprint, val, string(buf) ); //傳遞參數
#include <iostream>#include <string>#include <thread>using namespace std;class A {public:int m_i;A(int i) :m_i(i) { cout << "A::A(int i)函數執行了" << endl; }A(const A &other) :m_i(other.m_i) { cout << "A::A(const A &other)函數執行了" << endl; }~A() { cout << "A:: ~A()函數執行了" << endl; }};void myprint(const int i, const A & p_a ) {cout << &p_a << endl; return;}int main(){int m_val = 1;int n_val = 22;thread mythread(myprint, m_val, n_val); mythread.join();std::cout << "主線程收尾" << std::endl;return 0;}由輸出可知該構造是發生在main函數執行完畢後才開始的。主線程退出後n_val的內存空間被回收了,此時還用n_val(無效了)去構造A類對象,這會導致一些未定義的行為。
我們期望n_val能夠通過A類的類型轉換構造函數構造出對象,但是遺憾的發現直到主線程退出了都沒構造出我們想要的對象然後傳給子線程。
我們使用顯示地進行轉換,構造出臨時對象,然後調用拷貝構造函數將臨時對象拷貝給線程函數的第二個參數p_a.
thread mythread(myprint, m_val, A(n_val));
總結臨時對象作為線程參數繼續講線程id概念臨時對象構造時機抓捕#include <iostream>#include <string>#include <thread>using namespace std;class A {public:int m_i;A(int i) :m_i(i) { cout << "A::A(int i)函數執行了" << this << " ThreadId " \<< std::this_thread::get_id()<< endl; }A(const A &other) :m_i(other.m_i) { cout << "A::A(const A &other)函數執行了" << this \<< " ThreadId " << std::this_thread::get_id() << endl; }~A() { cout << "A:: ~A()函數執行了" << this << " ThreadId " \<< std::this_thread::get_id() << endl; }};void myprint(const A &p_a ) {cout << "子線程myprint()參數地址:" << &p_a << " ThreadId " \<< std::this_thread::get_id() << endl;return;}int main(){cout << "主線程ID" << std::this_thread::get_id() << endl;int n_val = 69;thread mythread(myprint, n_val); mythread.join();std::cout << "主線程收尾" << std::endl;return 0;}thread mythread(myprint, A(n_val));
void myprint(const A p_a )
傳遞類對象、智能指針作為線程參數在線程中修改變量的值不會影響到主線程。
#include <iostream>#include <string>#include <thread>using namespace std;class A {public:mutable int m_i;A(int i) :m_i(i) { cout << "A::A(int i)函數執行了" << this << " ThreadId " \<< std::this_thread::get_id()<< endl; }A(const A &other) :m_i(other.m_i) { cout << "A::A(const A &other)函數執行了" << this \<< " ThreadId " << std::this_thread::get_id() << endl; }~A() { cout << "A:: ~A()函數執行了" << this << " ThreadId " \<< std::this_thread::get_id() << endl; }};void myprint(const A &p_a ) {p_a.m_i = 89;cout << "子線程myprint()參數地址:" << &p_a << " ThreadId " \<< std::this_thread::get_id() << endl;return;}int main(){cout << "主線程ID" << std::this_thread::get_id() << endl;A a(1);thread mythread(myprint, a);mythread.join();std::cout << "主線程結束" << std::endl;return 0;}【std::ref()】
#include <iostream>#include <string>#include <thread>using namespace std;class A {public:int m_i;A(int i) :m_i(i) { cout << "A::A(int i)函數執行了"<< endl; }A(const A &other) :m_i(other.m_i) { cout << "A::A(const A &other)函數執行了" << endl; }~A() { cout << "A:: ~A()函數執行了" << endl; }};void myprint(A &p_a ) {p_a.m_i = 89;cout << "子線程myprint()執行了" << endl;return;}int main(){A a(1);thread mythread(myprint, std::ref(a));mythread.join();std::cout << "主線程結束" << std::endl;return 0;}智能指針,想從一個堆棧到另一個堆棧,需要使用std::move()
#include <iostream>#include <string>#include <thread>using namespace std;void myprint(unique_ptr<int> ptr_u) {cout << "子線程myprint()執行了" << endl;return;}int main(){unique_ptr<int> m_ptr(new int(100));thread mythread(myprint, std::move(m_ptr));mythread.join();std::cout << "主線程結束" << std::endl;return 0;}用成員函數指針做線程函數#include <iostream>#include <string>#include <thread>using namespace std;class A {public:int m_i;A(int i) :m_i(i) { cout << "A::A(int i)函數執行了"<< endl; }A(const A &other) :m_i(other.m_i) { cout << "A::A(const A &other)函數執行了" << endl; }void func(int i) { cout << "A::func(int i)函數執行了" \<< " i = " << i << endl; }~A() { cout << "A:: ~A()函數執行了" << endl; }};int main(){A a_obj(11);thread mythread(&A::func, a_obj, 233);mythread.join();std::cout << "主線程結束" << std::endl;return 0;}【注】類對象使用引用方式傳遞
thread mythread(&A::func, &a_obj, 233);
thread mythread(&A::func, std::ref(a_obj), 233);
【operator()帶參數】
#include <iostream>#include <string>#include <thread>using namespace std;class A {public:int m_i;A(int i) :m_i(i) { cout << "A::A(int i)函數執行了"<< endl; }A(const A &other) :m_i(other.m_i) { cout << "A::A(const A &other)函數執行了" << endl; }void operator()(int i) { cout << "A::operator()執行了" \<< " i = " << i << endl; }~A() { cout << "A:: ~A()函數執行了" << endl; }};int main(){A a_obj(11);thread mythread(a_obj, 666);mythread.join();std::cout << "主線程結束" << std::endl;return 0;}thread mythread(std::ref(a_obj), 999);
thread mythread(&a_obj, 999);
使用detach注意事項小結