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;
}