1.detach使用时分析
使用detach时,子线程一定不要传入指针
#include<iostream>
#include<thread>
using namespace std;void my_print(const int& num1,const char* str) {cout << num1 << " " << str << endl;
}
//主进程结束后,才开始对子进程中的值进行拷贝。但是主进程释放了str1,子进程接收时会出现问题。
int main() {int num1 = 1;char str1[] = "hello,world!";thread obj1(my_print,num1,str1);obj1.detach();cout << "主进程结束运行" << endl;return 0;
}
如果采用临时类对象作为参数,传入到thread中,thread会调用拷贝构造函数,对传入变量进行拷贝,然后再为自线程所使用。
下面的代码采用引用来接收类对象,如果不采用引用的话,系统还会再构造一次对象,这样会出现3次构造,浪费时间。
#include<iostream>
#include<thread>
using namespace std;class son_thread {
public:int m_a;son_thread(int a):m_a(a) {cout << "构造函数的调用" << endl;}~son_thread() {cout << "析构函数的调用" << endl;}
};void my_print(const int a,const son_thread& st) {cout << a << " " << st.m_a << endl;
}
int main() {int num1 = 1;int num2 = 10;thread obj1(my_print, num1,son_thread(num2));obj1.detach();cout << "主进程结束运行" << endl;return 0;
}
2. 临时对象
1.如果对象采用隐式转换,将会在子线程中进行构造对象;
2.如果对象采用显示转换,将会在主线程中进行构造对象,并会调用拷贝构造函数。
this_thread::get_id()---->显示线程的id号
注意:
当采用隐式传递时,是在子线程进行类对象构造,但是此时主线程已经销毁,主线程内的局部变量已经释放,此时操作会有危险。
当采用显式构造是,首先会在主线程构造出一个临时对象,然后在主线程中进行复制拷贝构造,随后在主线程内将临时对象进行释放。
#include<iostream>
#include<thread>
using namespace std;
class son_thread {
public:int m_a;son_thread(int a) :m_a(a) {cout << "son_thread构造函数调用" << this_thread::get_id() << endl;}son_thread(const son_thread& base):m_a(base.m_a) {cout << "son_thread拷贝构造函数的调用" << this_thread::get_id()<< endl;}~son_thread() {cout << "son_thread析构函数调用" << this_thread::get_id()<< endl;}
};
void my_print(const son_thread& base) {cout << base.m_a << " my_print调用" << this_thread::get_id()<< endl;
}
int main() {int temp_a = 1;cout << "主线程的id:" << this_thread::get_id() << endl;//thread obj1(my_print, temp_a);thread obj1(my_print, son_thread(temp_a));obj1.join();cout << "主线程调用完毕:" << this_thread::get_id() << endl;return 0;
}
3.传递智能指针、类对象
因为在传递类对象是,子线程会调用拷贝构造函数,因此子线程修改类对象成员变量时,并不会修改主线程内的对象成员变量。
此时我们可以用:std::ref()函数
在传入unique_ptr智能指针时,可以使用std::move()对智能指针进行更改。
#include<iostream>
#include<thread>
using namespace std;
class son_thread {
public:int m_a;son_thread(int a) :m_a(a) {cout << "son_thread构造函数调用" << this_thread::get_id() << endl;}son_thread(const son_thread& base) :m_a(base.m_a) {cout << "son_thread拷贝构造函数的调用" << this_thread::get_id() << endl;}~son_thread() {cout << "son_thread析构函数调用" << this_thread::get_id() << endl;}
};
void my_print(unique_ptr<int>temp_pt) {cout << *temp_pt << " my_print调用" << this_thread::get_id() << endl;
}
int main() {int temp_a = 1;cout << "主线程的id:" << this_thread::get_id() << endl;unique_ptr<int>u_pt(new int (100));thread obj1(my_print, std::move(u_pt));obj1.join();cout << "主线程调用完毕:" << this_thread::get_id() << endl;return 0;
}
4.将类函数的函数作为入口函数
#include<iostream>
#include<thread>using namespace std;
class son_thread {
public:int m_a;son_thread(int a) :m_a(a) {cout << "son_thread构造函数调用" << this_thread::get_id() << endl;}son_thread(const son_thread& base) :m_a(base.m_a) {cout << "son_thread拷贝构造函数的调用" << this_thread::get_id() << endl;}~son_thread() {cout << "son_thread析构函数调用" << this_thread::get_id() << endl;}void my_print(const int a ) {cout << a << " 类内函数的调用" << endl;}
};int main() {cout << "主线程的id:" << this_thread::get_id() << endl;son_thread s1(10);thread obj1(&son_thread::my_print, s1, 100);obj1.join();cout << "主线程调用完毕:" << this_thread::get_id() << endl;return 0;
}