多线程
创建临时对象为线程参数用detach时,子线程引用主函数中的参数会引发很多问题,例如:变量还没有复制到子线程中就已经被收回。若传递int这种简单类型参数,建议是值传递,必要用引用和指针,避免界外生枝。如果传递类对象,避免隐式类型转换。全部在创建线程这一行构建出临时对象来,然后在函数参数里,用引用来接,否者会多构造一次对象。建议不适用detach(),只使用join():这样就不会出现局部变量失效导
·
创建临时对象为线程参数
用detach时,子线程引用主函数中的参数会引发很多问题,例如:变量还没有复制到子线程中就已经被收回。
- 若传递int这种简单类型参数,建议是值传递,必要用引用和指针,避免界外生枝。
- 如果传递类对象,避免隐式类型转换。全部在创建线程这一行构建出临时对象来,然后在函数参数里,用引用来接,否者会多构造一次对象。
建议不适用detach(),只使用join():这样就不会出现局部变量失效导致的线程对非法内存的引用。
#include<iostream>
#include<thread>
using namespace std;
class A
{
public:
int a;
A(int ai) :a(ai)
{
cout << "我是构造函数" << "线程id:" << std::this_thread::get_id() << endl;
}
A(const A &a)
{
cout << "我是拷贝构造函数" << "线程id:" << std::this_thread::get_id() << endl;
}
~A()
{
cout << "我是析构函数" << "线程id:" << std::this_thread::get_id() << endl;
}
};
void myfunc(int i,A &a)//用引用接
{
cout << "myfunc函数执行" << "线程id:" << std::this_thread::get_id() << endl;
}
int main()
{
int var1 = 9;
int var2 = 10;
cout << "主线程id:" << std::this_thread::get_id() << endl;
thread t1(myfunc, var1, A(var2));//创建一个临时对象
t1.detach();
system("pause");
return 0;
}
结果:
可以看出子线程会进行类创建,这样就不会有问题了,这与这里为什么在主线程中构建了好几次类,具体原因我也不清楚,如果有网友知道原因,可以给我留言。
- 线程id的概念,每个线程都对应一个数字类型的id,并且每个线程的id是唯一的,获得线程id:std::this_thread::get_id().
/**************用隐士类型转化的时候,类对象是在子线程中创建的**********************/ /**************可以分别在类的构造函数和子线程入口函数中打印当前线程id的方式加以验证**********************/ #include<iostream> #include<thread> using namespace std; class A { public: int a; A(int ai) :a(ai) { cout << "我是构造函数" << "线程id:" << std::this_thread::get_id() << endl; } A(const A &a) { cout << "我是拷贝构造函数"<< "线程id:" << std::this_thread::get_id() << endl; } ~A() { cout << "我是析构函数"<< "线程id:" << std::this_thread::get_id() << endl; } }; void myfunc(int i,A a)//直接用对象接受 { cout << "myfunc函数执行" << "线程id:" << std::this_thread::get_id() << endl; } int main() { int var1 = 9; int var2 = 10; cout << "主线程id:" << std::this_thread::get_id() << endl; thread t1(myfunc, var1, var2);//用隐式类型转化的方式 t1.detach(); system("pause"); return 0; }
-
结果为:
从以上的例子可以看出,在一般情况下,为了安全起见,操作系统会将主线程中的变量拷贝一份到子线程中,也就是如果在子线程中对变量进行修改,不会影响到主线程中的参数变化。那么会有一个问题,如果我需要子线程中的变化传到主线程中,就需要用到std::ref()函数,表示直接主线程中的地址传进去。这样就不会调用拷贝构造函数了。
#include<iostream> #include<thread> using namespace std; class A { public: int a; A(int ai) :a(ai) { cout << "我是构造函数" << "线程id:" << std::this_thread::get_id() << endl; } A(const A &a) { cout << "我是拷贝构造函数" << "线程id:" << std::this_thread::get_id() << endl; } ~A() { cout << "我是析构函数" << "线程id:" << std::this_thread::get_id() << endl; } }; void myfunc(A &a)//此处要用引用接受。否者不能进行修改 { cout << "myfunc函数执行" << "线程id:" << std::this_thread::get_id() << endl; a.a=20; } int main() { cout << "主线程id:" << std::this_thread::get_id() << endl; int var1 = 9; int var2 = 10; A a(var1); cout << "线程执行前:" << a.a << endl; thread t1(myfunc, std::ref(a));//用隐式类型转化的方式 //t1.detach(); t1.join(); cout << "线程执行后:" << a.a << endl; system("pause"); return 0; }
注意:在子线程函数中一定要用引用接受,如果没有用引用又相当于传进去的是副本。
用智能指针创建线程
更多推荐
已为社区贡献2条内容
所有评论(0)