C++并行开发3-线程传参详解,detach()大坑,成员函数做线程函数
thread传入类对象
#include <iostream>
#include <string>
#include <thread>
using namespace std;
void myprint(const int i, string mybuf) {
cout << i << endl;
cout << mybuf << endl; //直接传string也是可以的,因为会拷贝构造
}
//void myprint(const int& i, //通过shift + F9 调试发现,这里传的引用但是也会拷贝一下,是值传递,这样即使main退出,也是安全的
// char* mybuf) { //但是堆上的数据是不安全的,是传引用,指针和引用都是由问题的
// cout << i << endl;
// cout << mybuf << endl; //直接传string也是可以的,因为会拷贝构造
//}
int main()
{
//传递临时对象作为线程参数
int mval = 1;
int &myvaly = mval;
char mybuf[] = "this is a test ";
//thread myobj(myprint, mval, mybuf);
//问题 mybuf是什么时候转化为string 的, 有可能出现mybuf都被回收了,系统才用mybuf转string的可能性
thread myobj(myprint, mval, string(mybuf)); //这里直接将mybuf 转化为 string
myobj.join();
cout << "主线程运行完毕" << endl;
return 0;
}
上述代码总结,栈上的数据在创建线程的时候会拷贝,但是堆上的数据在创建线程的时候不会拷贝
class A {
public:
int m_i;
A(int i) : m_i(i) { //这种构造函数也可以被称为强制类型转化函数
cout << "A 的构造函数" << endl;
}
A(const A& other) :m_i(other.m_i) {
cout << "A 的拷贝构造函数" << endl;
}
~A() {
cout << "A的析构函数" << endl;
}
};
void myprint(const int i, const A& mybuf) {
cout << i << endl;
cout << &mybuf << endl;
}
int main()
{
//传递临时对象作为线程参数
int mval = 1;
int &myvaly = mval;
int second = 12;
thread myobj(myprint, mval, mval); //这里直接将mybuf 转化为 string
myobj.detach();
cout << "主线程运行完毕 111" << endl;
return 0;
}
这种情况下,有可能出现mval还没有强制转换,就已经线程结束的情况,从下图可以看到,A有可能没有构造完毕,主线程就推出了
int main()
{
//传递临时对象作为线程参数
int mval = 1;
int &myvaly = mval;
int second = 12;
//thread myobj(myprint, mval, mval); //这里直接将mybuf 转化为 string
thread myobj(myprint, mval,A(mval)); //在创建线程的同时构造临时对象的方法是可行的
myobj.detach();
cout << "主线程运行完毕 111" << endl;
return 0;
}
小结
1. 若传递的是int这种简单的类型参数,建议直接值传递,不要传引用,以免节外生枝
2. 如果传递类对象,避免隐式类型转换, 全部都在传递参数的时候,构建一个临时变量,用引用来接,否则系统就会构造3次
线程id
线程id 可以通过std::this_thread::get_id()
传递类对象,智能指针作为线程参数
#include <iostream>
#include <string>
#include <thread>
using namespace std;
class A {
public:
mutable int m_i;
A(int i) : m_i(i) { //这种构造函数也可以被称为强制类型转化函数
cout << "A 的构造函数" << "Id : " << std::this_thread::get_id() << endl;
}
A(const A& other) :m_i(other.m_i) {
cout << "A 的拷贝构造函数" << std::this_thread::get_id() << endl;
}
~A() {
cout << "A的析构函数" << std::this_thread::get_id() << endl;
}
};
void myprint(const int i, const A& mybuf) {
cout << i << endl;
mybuf.m_i = 199; //已经拷贝构造了,这里修改但是没有用
}
int main()
{
//传递临时对象作为线程参数
int mval = 1;
int &myvaly = mval;
int second = 12;
A a(mval);
//thread myobj(myprint, mval, a); //这里传入进去并不会修改A里面的值
thread myobj(myprint, mval, std::ref(a)); //这里传入进去并不会修改A里面的值
// 不加std::ref myprin里面就必须要加上const 并且引用,否则会报错
myobj.detach();
cout << "A " << a.m_i << endl;
cout << "主线程Id: " << std::this_thread::get_id() << endl;
cout << "主线程运行完毕 111" << endl;
return 0;
}
可以使用std::ref()改变类中的成员数据。
void myprint(unique_ptr<int> i) {
cout << "i = " << i << endl;
}
int main()
{
unique_ptr<int> myp(new int(100));
//shared_ptr<int> myp(new int(100));
thread mtobj(myprint, myp); //报错 unique_ptr不支持拷贝构造, shared_ptr就可以
//thread mtobj(myprint, std::move(myp));
mtobj.join();
return 0;
}
unique_ptr不支持拷贝构造, shared_ptr就可以, 如果一定要用move也可以使用std::move
#include <iostream>
#include <string>
#include <thread>
using namespace std;
class A {
public:
mutable int m_i;
A(int i) : m_i(i) { //这种构造函数也可以被称为强制类型转化函数
cout << "A 的构造函数" << "Id : " << std::this_thread::get_id() << endl;
}
A(const A& other) :m_i(other.m_i) {
cout << "A 的拷贝构造函数" << std::this_thread::get_id() << endl;
}
void thread_word(int num) {
cout << "num is " << num << endl;
}
void operator()(int num) {
cout << "operator " << num << endl;
}
~A() {
cout << "A的析构函数" << std::this_thread::get_id() << endl;
}
};
//void myprint(const int i, const A& mybuf) {
// cout << i << endl;
// mybuf.m_i = 199; //已经拷贝构造了,这里修改但是没有用
//}
void myprint(unique_ptr<int> i) {
cout << "i = " << i << endl;
}
int main()
{
A myobj(1);
std::thread mytobj(&A::thread_word, myobj, 500);
//std::thread mytobj(myobj, 500);
mytobj.join(); //这里只能用到join 因为thread中需要传入myobj
return 0;
}
使用类成员函数作为线程对象 总结:使用std::ref不会再使用拷贝构造函数,std::move是真的左移
- Title: C++并行开发3-线程传参详解,detach()大坑,成员函数做线程函数
- Author: FengLY
- Created at : 2023-06-18 22:40:09
- Updated at : 2023-06-18 22:55:37
- Link: https://zhouaq.com/2023/06/18/C++并行开发3-线程传参详解,detach()大坑,成员函数做线程函数/
- License: This work is licensed under CC BY-NC-SA 4.0.
Comments