void myprint(const int i,const string &pmybuf)
{
cout<<i<<endl;//分析發現i並不是mvar的引用,而是值傳遞。但是並不推薦這麼使用
cout<<pmybuf.c_str()<<endl;//指針在detach子線程時,絕對會有問題。
return ;
}
int main()
{
//傳遞臨時對象作爲線程參數
int mvar =1;
int &myvar=mvar;
char buf[]="this a test!";
第一個參數是函數名,從後面開始就是傳入這個線程函數的參數
thread my_th(myprint,mvar,buf);
buf是在什麼時候轉換成string的?
事實上存在,buf的內存被回收了,系統才用buf去轉成string。
//my_th.join();
my_th.detach();//主線程退出,mvar在子線程中會不會出問題?
cout<<"I LOve CHNIA"<<endl;
return 0;
}
將上面的代碼換成這個就不會有問題
thread my_th(myprint,mvar,string(buf));//生成一個臨時string對象它會綁定到
這裏將buf轉換成string對象,這是一個可以保證在線程中安全的方法。
thread my_th(myprint,mvar,A(a));
class A{
public:
int m_i;
A(int a):m_i(a){cout<<"構造函數。。。"<<std::this_thread::get_id()<<endl;}
A(const A &a):a.m_i{cout<<"拷貝構造函數。。。"<<std::this_thread::get_id()<<endl;}
~A()cout<<"析構函數。。。"<<std::this_thread::get_id()<<endl;}
};
int main()
{
int a=1;
int vara=12;
thread my_th(myprint,mvar,A(vara));
cout<<"I LOve CHNIA"<<endl;
return 0;
}
總結:
1、如果傳遞int這種簡單的參數類型,建議使用值傳遞,不要使用引用。/2、如果傳遞類對象,避免隱式類型轉換,全部都在創建線程這一行就構建臨時對象,然後在函數參數裏使用引用來接,否則系統還會多構造一次對象。
建議不使用detach(),只是有jion()。
線程id的概念:
id是一個數字:每個線程,都對應一個線程id,都不同。
c++函數庫裏面的函數來獲取 std::this_thread::get_id()來獲取。
使用類對象創建線程
class A{
public:
mutable int m_i;
A(int a):m_i(a){cout<<"構造函數"<<std::this_thread::get_id()<<endl;}
A(const A &a):m_i(a.m_i){cout<<"拷貝構造函數"<<endl;}
~A(){cout<<"析構函數"<<std::this_thread::get_id()<<endl;}
void print(const A &buf)
{
buf.m_i =199;//修改值不會影響main函數
cout<<"子線程的參數地址:"<<&buf<<"threadID:"<<std::this_thread::get_id()<<endl;
}
//std::ref向線程中傳遞類對象,編譯器都會安裝
};
int main()
{
A myobj(10);
std::thread myth(print,myobj);//將類對象作爲線程的參數,會調用到對象拷貝構造函數
向線程中傳遞類對象,編譯器都會按照拷貝的方式傳入
如果想傳遞進去的是引用,而不是拷貝,則需要使用std::ref
//std::thread myth(print,std::ref(myobj));這樣傳遞的就是真的引用,真的會改變這個值,不能使用detach()
myth(print,&myobj);這樣傳遞的就是真的引用,真的會改變這個值,不能使用detach()
myth.join();
return 0;
}
-----------------------------
void print(unique_ptr<int> x)
{
cout<<"子線程的參數地址:"<<&buf<<"threadID:"<<std::this_thread::get_id()<<endl;
}
int main()
{
unique_ptr<int> p_int(new int(100));//獨佔方式指針
std::thread myth(print,std::move(p_int));//修改佔方式指針使用std::move()
myth.join();//在這種情況下,千萬不能detach(),不然線程不安全。
return 0;
}
----------------------------------------------------------
class A{
public:
A(int a):m_i(a){cout<<"構造函數"<<std::this_thread::get_id()<<endl;}
A(const A &a):m_i(a.m_i){cout<<"拷貝構造函數"<<endl;}
~A(){cout<<"析構函數"<<std::this_thread::get_id()<<endl;}
void thread_work(int num)
{
cout<<"子線程執行了:"<<this<<"threadID = "<<std::this_thread::get_id()<<endl;
}
int m_i;
};
int main()
{
A myobj(10);//生成一個類對象
std::thread myth(&A::thread_work,myobj,15);
//這邊的myobj放入子線程會調用拷貝構造函數
myth.join();
return 0;
}
----------------------------------------------------------
class A{
public:
A(int a):m_i(a){cout<<"構造函數"<<std::this_thread::get_id()<<endl;}
A(const A &a):m_i(a.m_i){cout<<"拷貝構造函數"<<endl;}
~A(){cout<<"析構函數"<<std::this_thread::get_id()<<endl;}
void operator(int num)
{
cout<<"子線程()執行了:"<<this<<"threadID = "<<std::this_thread::get_id()<<endl;
}
int m_i;
};
int main()
{
A myobj(10);//生成一個類對象
std::thread myth(myobj,15);//這邊的myobj放入子線程會調用拷貝構造函數,複製出一個對象。
myth.join();
return 0;
}