关于std::thread
线程传参的思考
最重要要记住的一点是:参数要拷贝到线程独立内存中,不管是普通类型、还是引用类型。
对于传递参数是引用类型,需要注意:
-
1.当指向动态变量的指针
(char *)
作为实数,string const&
作为形参,在传递的时候先人为增加动态变量转换string
的操作。
原因:std::thread
传递参数是直接拷贝一份实参到线程独立内存的,所以假如不事先转换为string
,在创建线程传递参数到std::thread
构造函数后会发生隐性参数转换,但是这时类型转换操作可能会发生错误,如果发生oops,那么std::thread
又只是拷贝实参的一份到自己独立内存,那么自己操作的只是一个“半成品”对象,对原来的动态变量的指针指向的字面常量没有丝毫影响。
解决办法:在传递到std::thread
构造函数前就将字面值转换为std::string
对象。(std::thread t(func, std::string("hello")))
-
2.期望传递一个引用,在新线程修改引用对象时,需要使用
std::ref()
修饰实参。
原因:std::thread
构造时传参传的只是实参的一份拷贝,拷贝,拷贝,不会像普通函数传参那样,函数形参是引用类型,实参是原型变量,此时调用到函数时函数会获取到对应变量的引用,修改形参引用的变量可以真正修改实参的值。std::thread
传递的只是一份拷贝,传递过去一个变量值,线程形参引用的只是这个变量的拷贝的引用,对它的操作于实参没有任何影响。
解决办法:std::thread
形参是引用时,在std::thread t()
创建线程的时候,需要使用std::ref()
转换参数为引用,那么线程函数获取到的就是对应变量的真正引用,对它的操作就能影响真正的实参。(void func(string& data) std::thread t(func, std::ref(data)))
-
3.如果想对一个对象,只通过传参来被新线程使用,即把对象的使用权转移给新线程内部变量,被转移对象在主线程就被销毁,达到全局对象唯一性。
解决办法:使用`std::move()修饰参数,可实现所有权转移。