1. デタッチ使用時の解析
デタッチを使用する場合、子スレッドはポインターを渡してはなりません。
#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;
}
一時クラス オブジェクトがパラメータとして使用され、スレッドに渡される場合、スレッドはコピー コンストラクターを呼び出して受信変数をコピーし、それをスレッドで使用します。
次のコードでは、参照を使用してクラス オブジェクトを受け取ります。参照を使用しない場合、システムはオブジェクトを再度構築するため、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;
}