启动线程需要注意的问题
在上一节,我们已经学会了最简单的线程初始化,用的是一个无参的函数来创建线程的。
那么,我们还有别的线程启动方式吗?有的。
下面举一个仿函数对象初始化线程的例子。
我们知道,在C++中,有一个东西叫做仿函数,它本质上是一个类,只是重载了函数调用运算符。是可以用它的对象来初始化线程的
在这种情况下,有两个需要注意的地方:
- A:提供的函数对象会复制到新线程的空间当中,
- B:如果你不想创建对象,使用了匿名对象Fun() 去构造线程,那么这个时候C++编译器会将其视为函数声明。解决的办法如下:
向线程过程函数传递参数
若想向其传递参数,则将这些参数作为 std::thread 构造函数的附加参数即可。
奇怪的事情发生了,我们为了提高效率明明传递的是引用,而且在函数 test 中修改了它的值,为什么在主线程中还是显示 hello world 呢?
- 在默认情况下,这些参数会拷贝一份副本到新线程的独立内存空间中,是值传递,传递给了函数或是可调用对象,所以同样可以看到下面的情况
修改为引用传递的办法是: std::thread t1(std::ref(f));
传参时需要注意的问题
考虑下面的例子:
对线程 t1 而言,这里使用 const char* 类型的实参到 string 类型的转化。
对线程 t2 而言,buffer 是指针,由于使用了 detach,很可能在 buffer 转化为 string 以前 test 就执行结束了。可能会出现 std::thread 的构造函数拷贝的是 buffer 而非 string
因此,上面的代码需要改为:
std::thread t2(print, std::string(buffer));