一、传递临时对象作为线程参数
结论:只要用临时构造A类对象作为参数传递给线程,那么就一定能够在主线程执行完毕之前把线程的第二个参数构建出来,从而确保即便detach()了,子线程也能安全运行
void MyPrint(const int &num, const string &buf)
{
cout << num << endl;
cout << buf << endl;
}
int main()
{
int num = 1;
int &m_num = num;
char buf[] = "this is test";
thread obj(MyPrint, m_num, buf); //不安全的
//thread obj(MyPrint, m_num, string(buf)); // 安全的 //我们这里直接将buf转换成string对象,
//可以保证在线程中使用是有效的,(先调用普通构造函数,再调用拷贝构造函数)
obj.join();
//如果此处是用detach(),会存在主线程运行结束,临时对象对象被销毁的情况
cout << "I Love China" << endl;
//system("pause");
return 0;
}
使用detach()时总结:
- 若传递int 这种简单类型参数,建议都是值传递,不要用引用。
- 如果传递类对象,应避免隐式类型转换。应该全部在创建线程这一行就构造出临时对象来,然后在函数参数里面用引用来接,否则还会调用一次拷贝构造函数。
- 所以建议不适用detach(),只使用join(),这样就不存在局部变量失效导致线程对内存的非法引用问题。
二、线程id 的概念
- 每个线程都对应着不同的线程id ,可以通过C++标准库函数获取
std::this_thread::get_id();
三、智能指针最为线程参数
void MyPrint(const unique_ptr<int> ptr) //独占式指针
{
cout << "子线程Id = " << std::this_thread::get_id() << endl;
}
int main()
{
unique_ptr<int> ptr(new int(100));
thread obj(MyPrint, std::move(ptr));
obj.join();
return 0;
}
四、用成员函数指针作为线程参数
class Test
{
public:
Test() {};
~Test() {};
void Thread(const int& num)
{
cout << "子线程执行了" << endl;
}
};
int main()
{
Test test;
thread obj(&Test::Thread, test, 10); //std::ref()传递真正的引用
obj.join();
return 0;
}