#include#include using namespace std; void myprint(const int& i,char* pmybuf) { printf("&i=%pn",&i); // i 虽然是引用,但是是值拷贝 cout< detach()的时候,参数一定不能传指针,最好不要传引用,虽然引用是值拷贝的方式进行传递。
#include#include using namespace std; class A { public: int m_i; A(int a):m_i(a) {cout<<"A::A(int a) constructor is doing..."< 总结:
1.如果传递int等简单类型,建议都是值传递,不要用应用,防止节外生枝。
2.如果传递类对象,避免隐士类型转化。全部都在创建线程这一行就构建出临时对象来,然后在函数参数里,用引用来接,否则系统还会构造出一次对象出来,避免浪费资源。
3.终极结论,建议不适用detach(),只使用join(),这样就不存在局部变量失效导致线程对内存的非法引用问题。除法万不得已,不要使用detach().
二、临时对象作为线程参数继续讲,用测试大法
1.为什么构造临时对象就安全了?探索根本原因,知其然,而知其所以然。
2.1 线程id,每个线程实际上都对应的是一个数字,不同的线程所对应的数字肯定是不一样的,线程id通过std::this_thread::get_id()来获取。
#include#include using namespace std; class A { public: int m_i; A(int a):m_i(a) {cout<<"A::A(int a) constructor is doing,this="< thread myobj(myprint2,mvar); //这种方式是在子线程中构造A对象,如果用detach(),会出现致命的问题。
thread myobj(myprint2,A(mvar));这种方式是在主线程中构造A对象,如果用detach(),就不会出现致命的问题。
三:传递类对象,智能指针作为线程参数
std::ref 函数 诞生的原因:
在多线程编程中,主线程和辅线程在进行参数传递的时候,不管是进行值传递,还是引用传递,编译器为了数据安全都是进行拷贝一份。那么这样其实就违背了引用的正常语义了,那么std::ref 函数就诞生了。
#include#include using namespace std; class A { public: mutable int m_i; A(int a):m_i(a) {cout<<"A::A(int a) constructor is doing,this="< #include using namespace std; class A { public: int m_i; A(int a):m_i(a) {cout<<"A::A(int a) constructor is doing,this="< 用了std::ref 之后,用引用进行参数传递的时候,就符合了引用的本来的语义了。
线程中传递智能指针写法:
#include#include using namespace std; class A { public: int m_i; A(int a):m_i(a) {cout<<"A::A(int a) constructor is doing,this="< pzn) { } int main(){ unique_ptr myp(new int(100)); std::thread mytobj(myprint2,std::move(myp)); mytobj.join(); //此处一定不能用detach(),一定要用join(),因为用detach(),new int(100) 这块内存很可能被系统回收了,那么就不能够转移到 pzn 对象了。 cout<<"I Love China!"< 如果不用,std::move(myp) 就会编译不过。
std::move(myp) 表示 独占式智能指针,从主函数的myp对象转移到 子线程函数,中的 unique_ptr
pzn,pzn对象中。 四:成员函数指针做线程函数
#include#include using namespace std; class A { public: int m_i; A(int a):m_i(a) {cout<<"A::A(int a) constructor is doing,this="< pzn) { } int main(){ //unique_ptr myp(new int(100)); //std::thread mytobj(myprint2,std::move(myp)); //mytobj.join(); A myobj(10); std::thread mytobj(&A::thread_work,myobj,27); //std::thread mytobj(&A::thread_work,std::ref(myobj),27); mytobj.join(); cout<<"I Love China!"< //std::thread mytobj(&A::thread_work,std::ref(myobj),27); 改成这样就不会出现拷贝构造。
//std::thread mytobj(&A::thread_work,&myobj,27);
std::ref(myobj) 等价写法:&myobj
#include#include using namespace std; class A { public: int m_i; A(int a):m_i(a) {cout<<"A::A(int a) constructor is doing,this="< myp(new int(100)); //std::thread mytobj(myprint2,std::move(myp)); //mytobj.join(); A myobj(10); thread mytobj(std::ref(myobj),29); // not call copy construct //thread mytobj(&myobj,29); //error mytobj.join(); cout<<"I Love China!"<



