从前面的知识我们知道,
一 启动子线程的方法有如下几种:
1.普通函数 做为 线程的启动
thread mythread(mythreadmethod);
void mythreadmethod() {
cout << "mythreadmethod start..." << endl;
cout << "mythreadmethod end..." << endl;
}
int main()
{
thread mythread(mythreadmethod);
mythread.join();
}
2. 类对象 作为线程的启动
Teacher141 t1;
thread mythread1(t1);
Teacher141 t2;
thread mythread12(t2,20);
//创建线程的方法,使用operator()函数做为 线程的入口函数
class Teacher141 {
public:
void operator()() {
cout << "Teacher141 的 operator() 没有参数的方法被调用" << endl;
}
void operator()(int num ) {
cout << "Teacher141 的 operator(int num) 的方法被调用: num = " << num << endl;
}
int m_age;
};
//operator()()做thread 启动方法入口
void main() {
cout << " test thread start " << endl;
//operator()()做thread 启动参数
Teacher141 t1;
thread mythread1(t1);
//operator()(T t)做thread 启动参数
Teacher141 t2;
thread mythread12(t2,20);
mythread1.join();
mythread12.join();
cout << " test thread end " << endl;
}
3. 类成员函数 作为线程的启动,注意使用的格式
Teacher142 tea;
thread mythread(&Teacher142::writeTeacherName,&tea);
//类的成员函数做 线程启动函数入口
class Teacher142 {
public:
void writeTeacherName() {
for (int i = 0; i < 1000; i++) {
cout << " 子线程id 为 : " << this_thread::get_id() << " i = " << i << endl;
}
}
};
void main() {
Teacher142 tea;
thread mythread(&Teacher142::writeTeacherName,&tea);
for (int i = 0; i < 1000;i++) {
cout << "主线程id 为 : " << this_thread::get_id() << " i = " << i << endl;
}
mythread.join();
}
4. Lambda 表达式 做为线程的启动
void main() {
std::cout << "Hello World0 start!\n";
auto mylambdathread = []() {
cout << "mylambdathread start..." << endl;
cout << "mylambdathread end..." << endl;
};
thread mythread(mylambdathread);
mythread.join();
}
二 从主线程传递参数给子线程,使用join方法
从前面的知识点,我们已经掌握了可以从主线程 启动 新线程了。但是没有传递参数。
这一节,我们看怎么传递参数。
1. 传递普通类型: int num ,非引用
实参和传递过来的地址值是不同的
void fun143(int num) {
//num 的值 : 0x00000093fa6ff580 {200}
for (int i = 0; i < 10;i++) {
cout << "子线程 id为 = " << this_thread::get_id() << " i = " << i << " fun143 num = " << num << endl;
}
}
void main() {
//传递普通类型: int num ,非引用
int a = 200;//0x00000093fa30f724 {200}
thread mythread(fun143,a);
for (int i = 0; i < 10;i++) {
cout << " 主线程 id 为 " << this_thread::get_id()<< " i = " << i << endl;
}
mythread.join();
}
2.传递C++自带类型: string str,非引用
实参和传递过来的地址值是不同的
void fun144(string str) {
for (int i = 0; i < 10; i++) {
//子线程 id为 = 2976 i = 0 fun144 str = nihao & str 0000004C06EFF578
cout << "子线程 id为 = " << this_thread::get_id() << " i = " << i << " fun144 str = " << str << " &str " << &str << endl;
}
}
//传递C++自带类型: string str ,非引用
void main() {
string strsource ("nihao");
cout << "主线程 id 为 " << this_thread::get_id() << " strsource = " << strsource << " &strsource = " << &strsource << endl;
//主线程 id 为 17956 strsource = nihao & strsource = 0000004C06B5F928
thread mythread(fun144, strsource);
for (int i = 0; i < 10; i++) {
cout << " 主线程 id 为 " << this_thread::get_id() << " i = " << i << endl;
}
mythread.join();
}
3.传递 自定义类型 -非引用
copy 构造函数被调用了2次,这至少说明thread 类内部肯定做了很多事情
class Teacher145 {
public:
Teacher145(int age) :mage(age) {
cout << "Teacher145 构造函数 mage = " << mage << " this_thread::getid()" << this_thread::get_id()<< " this " << this<< endl;
}
Teacher145(const Teacher145& obj) {
this->mage = obj.mage;
cout << "Teacher145 copy 构造函数" << " this_thread::getid() = " << this_thread::get_id() << " this = " << this <<" &obj = " << &obj << endl;
}
~Teacher145() {
cout << "Teacher145 析构函数被调用" << " this_thread::getid() = " << this_thread::get_id() << endl;
}
private:
int mage;
public:
int getAge() {
return this->mage;
}
};
void fun145(Teacher145 temptea) {
cout << "子线程 this_thread::get_id() = " << this_thread::get_id() << " &temptea = " << &temptea << " temptea.getAge() = " << temptea.getAge() << endl;
for (int i = 0; i < 10; ++i) {
cout << "子线程 this_thread::get_id() = " << this_thread::get_id() << " iii = " << i << endl;
}
}
void main() {
Teacher145 tea(20);
cout << "主线程 this_thread::get_id() = " << this_thread::get_id() << " &tea = " << &tea << " tea.getAge() = " << tea.getAge()<<endl;
thread mythread(fun145, tea);
for (int i = 0; i < 10; ++i) {
cout << "主线程 this_thread::get_id() = " << this_thread::get_id() << " i = " << i << endl;
}
mythread.join();
//从实验结果来看,copy 构造函数被调用了2次,这至少说明thread 类内部肯定做了很多事情,
//Teacher145 构造函数 mage = 20 this_thread::getid()17876 this 0000001C7DBDF7F4
// 主线程 this_thread::get_id() = 17876 & tea = 0000001C7DBDF7F4 tea.getAge() = 20
// Teacher145 copy 构造函数 this_thread::getid() = 17876 this = 0000017077E01990 &obj = 0000001C7DBDF7F4
// Teacher145 copy 构造函数 this_thread::getid() = 8660 this = 0000001C7DEFF574 &obj = 0000017077E01990
// 主线程 this_thread::get_id() = 17876 i = 0
// 主线程 this_thread::get_id() = 17876 i = 1
// 主线程 this_thread::get_id() = 17876 i = 2
// 主线程 this_thread::get_id() = 17876 i = 3
// 主线程 this_thread::get_id() = 17876 i = 4
// 主线程 this_thread::get_id() = 17876 i = 5
// 主线程 this_thread::get_id() = 17876 i = 6
// 主线程 this_thread::get_id() = 17876 i = 7
// 主线程 this_thread::get_id() = 17876 i = 8
// 主线程 this_thread::get_id() = 17876 i = 9
// 子线程 this_thread::get_id() = 8660 & temptea = 0000001C7DEFF574 temptea.getAge() = 20
// 子线程 this_thread::get_id() = 8660 iii = 0
// 子线程 this_thread::get_id() = 8660 iii = 1
// 子线程 this_thread::get_id() = 8660 iii = 2
// 子线程 this_thread::get_id() = 8660 iii = 3
// 子线程 this_thread::get_id() = 8660 iii = 4
// 子线程 this_thread::get_id() = 8660 iii = 5
// 子线程 this_thread::get_id() = 8660 iii = 6
// 子线程 this_thread::get_id() = 8660 iii = 7
// 子线程 this_thread::get_id() = 8660 iii = 8
// 子线程 this_thread::get_id() = 8660 iii = 9
// Teacher145 析构函数被调用 this_thread::getid() = 8660
// Teacher145 析构函数被调用 this_thread::getid() = 8660
// Teacher145 析构函数被调用 this_thread::getid() = 17876
}
4.1传递普通类型,int & num 引用。注意形参必须是const 类型
注意的点:
线程启动函数的参数,必须是const 的,、否则会有build error。既然参数是const的,就意味着不能改变这个参数,
实际测试发现,即使传递的是引用,也不是同一个地址 ,这说明 thread类内部肯定做了特殊的处理。
void fun146(const int &num) {//注意,这里要使用const 标识
//num 的值 :=
for (int i = 0; i < 10; i++) {
cout << "子线程 id为 = " << this_thread::get_id() << " i = " << i << " fun146 num = " << num << " &num = " <<&num<< endl;
}
}
void main() {
//传递普通类型: int num ,引用
int a = 800;
cout << "主线程id = " << this_thread::get_id() << " a = " << a << " &a = " << &a << endl;
thread mythread(fun146, a);
for (int i = 0; i < 10; i++) {
cout << " 主线程 id 为 " << this_thread::get_id() << " i = " << i << endl;
}
mythread.join();
//主线程id = 8468 a = 800 & a = 000000F811AFF934
// 子线程 id为 = 13700 i = 0 fun146 num = 800 & num = 0000029227931990
// 主线程 id 为 8468 i = 0
// 主线程 id 为 8468 i = 1
// 子线程 id为 = 13700 i = 1 fun146 num = 800 & num = 0000029227931990
// 子线程 id为 = 13700 i = 2 fun146 num = 800 & num = 0000029227931990
// 子线程 id为 = 13700 i = 3 fun146 num = 800 & num = 0000029227931990
// 子线程 id为 = 13700 i = 4 fun146 num = 800 & num = 0000029227931990
// 子线程 id为 = 13700 i = 5 fun146 num = 800 & num = 0000029227931990
// 子线程 id为 = 13700 i = 6 fun146 num = 800 & num = 0000029227931990
// 子线程 id为 = 13700 i = 7 fun146 num = 800 & num = 0000029227931990
// 子线程 id为 = 13700 i = 8 fun146 num = 800 & num = 0000029227931990
// 子线程 id为 = 13700 i = 9 fun146 num = 800 & num = 0000029227931990
// 主线程 id 为 8468 i = 2
// 主线程 id 为 8468 i = 3
// 主线程 id 为 8468 i = 4
// 主线程 id 为 8468 i = 5
// 主线程 id 为 8468 i = 6
// 主线程 id 为 8468 i = 7
// 主线程 id 为 8468 i = 8
// 主线程 id 为 8468 i = 9
}
4.2传递普通类型,int & num 引用2- 从上面的例子看到,即使传递了引用 实参 和形参 的地址并不一致,如果我们就是有需要:在主线程将实参传递进入后,在子线程改动这个实参的值,应该怎么写呢?
void fun147( int &num) {//注意,这里没有加 const 标识
//num 的值 :=
for (int i = 0; i < 10; i++) {
cout << "子线程 id为 = " << this_thread::get_id() << " i = " << i << " fun147 num = " << num << " &num = " << &num << endl;
}
}
void main() {
//传递普通类型: int num ,引用要使用 ref(a)函数包裹起来,才能传递真正的引用
//关于ref函数这里有详细的介绍。https://www.jb51.net/program/294417n5g.htm
//也可以不用了解ref函数的详情,我们只要知道:由于thread 做了事情,这些事情将原来传递引用的方法发生了变化,需要使用ref函数包裹就好
int a = 800;
cout << "主线程id = " << this_thread::get_id() << " a = " << a << " &a = " << &a << endl;
thread mythread(fun147, ref(a));
for (int i = 0; i < 10; i++) {
cout << " 主线程 id 为 " << this_thread::get_id() << " i = " << i << endl;
}
mythread.join();
//主线程id = 12116 a = 800 & a = 000000E06CAFF9D4
// 主线程 id 为 12116 i = 0
// 主线程 id 为 12116 i = 1
// 主线程 id 为 12116 i = 2
// 主线程 id 为 12116 i = 3
// 主线程 id 为 12116 i = 4
// 主线程 id 为 12116 i = 5
// 主线程 id 为 12116 i = 6
// 主线程 id 为 12116 i = 7
// 主线程 id 为 12116 i = 8
// 主线程 id 为 12116 i = 9
// 子线程 id为 = 1296 i = 0 fun147 num = 800 & num = 000000E06CAFF9D4
// 子线程 id为 = 1296 i = 1 fun147 num = 800 & num = 000000E06CAFF9D4
// 子线程 id为 = 1296 i = 2 fun147 num = 800 & num = 000000E06CAFF9D4
// 子线程 id为 = 1296 i = 3 fun147 num = 800 & num = 000000E06CAFF9D4
// 子线程 id为 = 1296 i = 4 fun147 num = 800 & num = 000000E06CAFF9D4
// 子线程 id为 = 1296 i = 5 fun147 num = 800 & num = 000000E06CAFF9D4
// 子线程 id为 = 1296 i = 6 fun147 num = 800 & num = 000000E06CAFF9D4
// 子线程 id为 = 1296 i = 7 fun147 num = 800 & num = 000000E06CAFF9D4
// 子线程 id为 = 1296 i = 8 fun147 num = 800 & num = 000000E06CAFF9D4
// 子线程 id为 = 1296 i = 9 fun147 num = 800 & num = 000000E06CAFF9D4
}
5.1 传递 C++自带类型 string str , 引用.注意,形参必须是 const类型
string 类型也一样,不是真正的引用 ,线程入口函数的参数要用const 修饰,否则会有build error
void fun148(const string &str) {//注意,这里要使用const 标识
for (int i = 0; i < 10; i++) {
cout << "子线程 id为 = " << this_thread::get_id() << " i = " << i << " fun148 string = " << str << " &str = " << &str << endl;
}
}
void main() {
//传递C++自带类型 string: string sourcestr ,引用
string strsource("nihao");
cout << "主线程id = " << this_thread::get_id() << " strsource = " << strsource << " &strsource = " << &strsource << endl;
thread mythread(fun148, strsource);
//for (int i = 0; i < 10; i++) {
// cout << " 主线程 id 为 " << this_thread::get_id() << " i = " << i << endl;
//}
mythread.join();
//主线程id = 16664 strsource = nihao & strsource = 0000005D6F91FBB8
// 子线程 id为 = 16288 i = 0 fun148 string = nihao & str = 000001E8F1D7BAE0
// 子线程 id为 = 16288 i = 1 fun148 string = nihao & str = 000001E8F1D7BAE0
// 子线程 id为 = 16288 i = 2 fun148 string = nihao & str = 000001E8F1D7BAE0
// 子线程 id为 = 16288 i = 3 fun148 string = nihao & str = 000001E8F1D7BAE0
// 子线程 id为 = 16288 i = 4 fun148 string = nihao & str = 000001E8F1D7BAE0
// 子线程 id为 = 16288 i = 5 fun148 string = nihao & str = 000001E8F1D7BAE0
// 子线程 id为 = 16288 i = 6 fun148 string = nihao & str = 000001E8F1D7BAE0
// 子线程 id为 = 16288 i = 7 fun148 string = nihao & str = 000001E8F1D7BAE0
// 子线程 id为 = 16288 i = 8 fun148 string = nihao & str = 000001E8F1D7BAE0
// 子线程 id为 = 16288 i = 9 fun148 string = nihao & str = 000001E8F1D7BAE0
}
5.2 传递 C++自带类型 string str , ref函数 包裹 引用.
void fun149( string &str) {
cout << "子线程 id为 = " << this_thread::get_id() << " fun149 string = " << str << " &str = " << &str << endl;
str = "str content changed";
}
void main() {
//传递C++自带类型 string: string sourcestr ,引用
string strsource("nihao");
cout << "主线程id = " << this_thread::get_id() << " strsource = " << strsource << " &strsource = " << &strsource << endl;
thread mythread(fun149, ref(strsource));
mythread.join();
cout << "strsource = " << strsource << endl;
//主线程id = 16728 strsource = nihao & strsource = 0000006C2270FA28
// 子线程 id为 = 14888 fun149 string = nihao & str = 0000006C2270FA28
// strsource = str content changed
}
6.1传递 自定义类型 引用, 线程入口函数参数必须是const类型,不然会有build error
class Teacher150 {
public:
Teacher150(int age) :mage(age) {
cout << "Teacher150 构造函数 mage = " << mage << " this_thread::getid()" << this_thread::get_id() << " this " << this << endl;
}
Teacher150(const Teacher150& obj) {
this->mage = obj.mage;
cout << "Teacher150 copy 构造函数" << " this_thread::getid() = " << this_thread::get_id() << " this = " << this << " &obj = " << &obj << endl;
}
~Teacher150() {
cout << "Teacher150 析构函数被调用" << " this_thread::getid() = " << this_thread::get_id() << endl;
}
private:
int mage;
public:
int getAge() {
return this->mage;
}
void setAge(int age) {
this->mage = age;
}
};
void func150(const Teacher150 & temptea) {
cout << "子线程id = " << this_thread::get_id() << " &temptea = " << &temptea << endl;
}
void main150() {
//传递 自定义 类的引用
Teacher150 tea(200);
cout << "主线程id = " << this_thread::get_id() << " &tea = " << &tea << endl;
thread mythread(func150,tea);
mythread.join();
//Teacher150 构造函数 mage = 200 this_thread::getid()15860 this 000000C1B95DFB14
// 主线程id = 15860 & tea = 000000C1B95DFB14
// Teacher150 copy 构造函数 this_thread::getid() = 15860 this = 0000021FCA5C2520 &obj = 000000C1B95DFB14
// 子线程id = 8600 & temptea = 0000021FCA5C2520
// Teacher150 析构函数被调用 this_thread::getid() = 8600
// Teacher150 析构函数被调用 this_thread::getid() = 15860
}
6.2 传递 自定义类型 ref 引用
class Teacher150 {
public:
Teacher150(int age) :mage(age) {
cout << "Teacher150 构造函数 mage = " << mage << " this_thread::getid()" << this_thread::get_id() << " this " << this << endl;
}
Teacher150(const Teacher150& obj) {
this->mage = obj.mage;
cout << "Teacher150 copy 构造函数" << " this_thread::getid() = " << this_thread::get_id() << " this = " << this << " &obj = " << &obj << endl;
}
~Teacher150() {
cout << "Teacher150 析构函数被调用" << " this_thread::getid() = " << this_thread::get_id() << endl;
}
private:
int mage;
public:
int getAge() {
return this->mage;
}
void setAge(int age) {
this->mage = age;
}
};
void func151( Teacher150 & temptea) {
cout << "子线程id = " << this_thread::get_id() << " &temptea = " << &temptea << endl;
temptea.setAge(89);
}
void main() {
//传递 自定义 类的引用
Teacher150 tea(200);
cout << "主线程id = " << this_thread::get_id() << " &tea = " << &tea << endl;
thread mythread(func151, ref(tea));
mythread.join();
cout << "tea.age = " << tea.getAge() << endl;
//Teacher150 构造函数 mage = 200 this_thread::getid()18644 this 000000109D95F6F4
// 主线程id = 18644 & tea = 000000109D95F6F4
// 子线程id = 11016 & temptea = 000000109D95F6F4
// tea.age = 89
// Teacher150 析构函数被调用 this_thread::getid() = 18644
}
7. 用 类成员函数的方式实现
class Teacher161 {
public:
Teacher161(int age) :mage(age) {
cout << "Teacher161 构造函数 mage = " << mage << " this_thread::getid()" << this_thread::get_id() << " this " << this << endl;
}
Teacher161(const Teacher161& obj) {
this->mage = obj.mage;
cout << "Teacher161 copy 构造函数" << " this_thread::getid() = " << this_thread::get_id() << " this = " << this << " &obj = " << &obj << endl;
}
~Teacher161() {
cout << "Teacher161 析构函数被调用" << " this_thread::getid() = " << this_thread::get_id() << endl;
}
private:
int mage;
public:
int getAge() {
return this->mage;
}
void setAge(int age) {
this->mage = age;
}
};
class Teacher160 {
public:
void fun143(int num) {
for (int i = 0; i < 10; i++) {
cout << "子线程 id为 = " << this_thread::get_id() << " i = " << i << " fun143 num = " << num << " & num = " << &num << endl;
}
}
void fun144(string str) {
for (int i = 0; i < 10; i++) {
cout << "子线程 id为 = " << this_thread::get_id() << " i = " << i << " fun144 str = " << str << " &str " << &str << endl;
}
}
void fun145(Teacher161 temptea) {
cout << "子线程 this_thread::get_id() = " << this_thread::get_id() << " &temptea = " << &temptea << " temptea.getAge() = " << temptea.getAge() << endl;
for (int i = 0; i < 10; ++i) {
cout << "子线程 this_thread::get_id() = " << this_thread::get_id() << " iii = " << i << endl;
}
}
void fun146(const int &num) {//注意,这里要使用const 标识
for (int i = 0; i < 10; i++) {
cout << "子线程 id为 = " << this_thread::get_id() << " i = " << i << " fun146 num = " << num << " &num = " << &num << endl;
}
}
void fun147(int &num) {//注意,这里没有加 const 标识
//num 的值 :=
for (int i = 0; i < 10; i++) {
cout << "子线程 id为 = " << this_thread::get_id() << " i = " << i << " fun147 num = " << num << " &num = " << &num << endl;
}
}
void fun148(const string &str) {//注意,这里要使用const 标识
//num 的值 :=
for (int i = 0; i < 10; i++) {
cout << "子线程 id为 = " << this_thread::get_id() << " i = " << i << " fun148 string = " << str << " &str = " << &str << endl;
}
}
void fun149(string &str) {
cout << "子线程 id为 = " << this_thread::get_id() << " fun149 string = " << str << " &str = " << &str << endl;
str = "str content changed";
}
void func150(const Teacher161 & temptea) {
cout << "子线程id = " << this_thread::get_id() << " &temptea = " << &temptea << endl;
}
void func151(Teacher161 & temptea) {
cout << "子线程id = " << this_thread::get_id() << " &temptea = " << &temptea << endl;
temptea.setAge(89);
}
public:
Teacher160() {
cout << "Teacher160 构造函数" << endl;
}
Teacher160(int age) :m_age(age) {
cout << "Teacher160 构造函数 int 执行" << endl;
}
Teacher160(const Teacher160& obj) {
this->m_age = obj.m_age;
cout << "Teacher160 copy 构造函数" << endl;
}
~Teacher160() {
cout << "Teacher160 析构函数" << endl;
}
private:
int m_age;
public:
void setTeacher160age(int age) {
this->m_age = age;
}
int getTeacher160age() {
return this->m_age;
}
};
7.1 普通类型做参数 非引用
void main(){
Teacher160 tea;
int num = 10;
cout << "主线程 " << this_thread::get_id() << " num = " << num << " &num = " <<&num << endl;
thread mythread(&Teacher160::fun143, &tea,num);
mythread.join();
// Teacher160 构造函数
// 主线程 16888 num = 10 & num = 0000001D49DBFAD4
// 子线程 id为 = 15876 i = 0 fun143 num = 10 & num = 0000001D4A0FF4E8
// 子线程 id为 = 15876 i = 1 fun143 num = 10 & num = 0000001D4A0FF4E8
// 子线程 id为 = 15876 i = 2 fun143 num = 10 & num = 0000001D4A0FF4E8
// 子线程 id为 = 15876 i = 3 fun143 num = 10 & num = 0000001D4A0FF4E8
// 子线程 id为 = 15876 i = 4 fun143 num = 10 & num = 0000001D4A0FF4E8
// 子线程 id为 = 15876 i = 5 fun143 num = 10 & num = 0000001D4A0FF4E8
// 子线程 id为 = 15876 i = 6 fun143 num = 10 & num = 0000001D4A0FF4E8
// 子线程 id为 = 15876 i = 7 fun143 num = 10 & num = 0000001D4A0FF4E8
// 子线程 id为 = 15876 i = 8 fun143 num = 10 & num = 0000001D4A0FF4E8
// 子线程 id为 = 15876 i = 9 fun143 num = 10 & num = 0000001D4A0FF4E8
// Teacher160 析构函数
}
7.2 string 类型做参数,非引用
Teacher160 tea;
string strsource("haoheiyou");
cout << "主线程 " << this_thread::get_id() << " strsource = " << strsource << " &strsource = " << &strsource << endl;
thread mythread(&Teacher160::fun144, &tea, strsource);
mythread.join();
//Teacher160 构造函数
// 主线程 16348 strsource = haoheiyou & strsource = 000000351C34F8A8
// 子线程 id为 = 13932 i = 0 fun144 str = haoheiyou & str 000000351C6FF438
// 子线程 id为 = 13932 i = 1 fun144 str = haoheiyou & str 000000351C6FF438
// 子线程 id为 = 13932 i = 2 fun144 str = haoheiyou & str 000000351C6FF438
// 子线程 id为 = 13932 i = 3 fun144 str = haoheiyou & str 000000351C6FF438
// 子线程 id为 = 13932 i = 4 fun144 str = haoheiyou & str 000000351C6FF438
// 子线程 id为 = 13932 i = 5 fun144 str = haoheiyou & str 000000351C6FF438
// 子线程 id为 = 13932 i = 6 fun144 str = haoheiyou & str 000000351C6FF438
// 子线程 id为 = 13932 i = 7 fun144 str = haoheiyou & str 000000351C6FF438
// 子线程 id为 = 13932 i = 8 fun144 str = haoheiyou & str 000000351C6FF438
// 子线程 id为 = 13932 i = 9 fun144 str = haoheiyou & str 000000351C6FF438
// Teacher160 析构函数
7.3传递自定义对象做参数,非引用
Teacher160 tea;
Teacher161 tea161(61);
cout << "主线程 " << this_thread::get_id() << " tea161 = " << &tea161 << endl;
thread mythread2(&Teacher160::fun145,tea, tea161);
mythread2.join();
//结果是Teacher161 的构造函数调用一次,copy 构造调用函数调用2次。析构了3次
//Teacher160 构造函数
// Teacher161 构造函数 mage = 61 this_thread::getid()19132 this 000000E5C099FC04
// 主线程 19132 tea161 = 000000E5C099FC04
// Teacher161 copy 构造函数 this_thread::getid() = 19132 this = 0000029CFC121E90 &obj = 000000E5C099FC04
// Teacher160 copy 构造函数
// Teacher161 copy 构造函数 this_thread::getid() = 16280 this = 000000E5C0CFF0E4 &obj = 0000029CFC121E90
// 子线程 this_thread::get_id() = 16280 & temptea = 000000E5C0CFF0E4 temptea.getAge() = 61
// 子线程 this_thread::get_id() = 16280 iii = 0
// 子线程 this_thread::get_id() = 16280 iii = 1
// 子线程 this_thread::get_id() = 16280 iii = 2
// 子线程 this_thread::get_id() = 16280 iii = 3
// 子线程 this_thread::get_id() = 16280 iii = 4
// 子线程 this_thread::get_id() = 16280 iii = 5
// 子线程 this_thread::get_id() = 16280 iii = 6
// 子线程 this_thread::get_id() = 16280 iii = 7
// 子线程 this_thread::get_id() = 16280 iii = 8
// 子线程 this_thread::get_id() = 16280 iii = 9
// Teacher161 析构函数被调用 this_thread::getid() = 16280
// Teacher160 析构函数
// Teacher161 析构函数被调用 this_thread::getid() = 16280
// Teacher161 析构函数被调用 this_thread::getid() = 19132
// Teacher160 析构函数
7.4 传递普通类型做参数,引用
Teacher160 tea;
int num = 60;
cout << "主线程 " << this_thread::get_id() << " num = " << &num << endl;
thread mythread2(&Teacher160::fun146, &tea, num);
mythread2.join();
//Teacher160 构造函数
// 主线程 11392 num = 00000085E5F0F4C4
// 子线程 id为 = 17400 i = 0 fun146 num = 60 & num = 000002453746A6D0
7.5传递普通类型做参数,使用ref函数包裹 引用
这两个地址是一样的,因此,改一个,另一个也会变。
Teacher160 tea;
int num = 60;
cout << "主线程 " << this_thread::get_id() << " num = " << &num << endl;
thread mythread2(&Teacher160::fun147, &tea, ref(num));
mythread2.join();
cout<<"num = "<< num << endl;
//Teacher160 构造函数
// 主线程 14780 num = 00000001000FFBE4
// 子线程 id为 = 18540 fun147 num = 60 & num = 00000001000FFBE4
// num = 888
// Teacher160 析构函数
7.6传递string 类型做参数,引用
Teacher160 tea;
string strscource("www.baidu.com");
cout << "主线程 " << this_thread::get_id() << " &strscource = " << &strscource << " strscource = " << strscource << endl;
thread mythread2(&Teacher160::fun148, &tea, strscource);
mythread2.join();
//主线程 16668 & strscource = 00000083DBD4F8D8 strscource = www.baidu.com
// 子线程 id为 = 12156 i = 0 fun148 string = www.baidu.com &str = 000001A5BA056200
7.7传递string 类型做参数,引用ref
Teacher160 tea;
string strscource("www.baidu.com");
cout << "主线程 " << this_thread::get_id() << " &strscource = " << &strscource << " strscource = " << strscource << endl;
thread mythread2(&Teacher160::fun149, &tea, ref(strscource));
mythread2.join();
cout << "strscource = " << strscource << endl;
结果:
Teacher160 构造函数
主线程 15976 &strscource = 000000DF866FFBB8 strscource = www.baidu.com
子线程 id为 = 16528 fun149 string = www.baidu.com &str = 000000DF866FFBB8
strscource = str content changed
Teacher160 析构函数
7.8传递自定义类型做参数,引用
Teacher160 tea;
Teacher161 tea161(81);
cout << "主线程 " << this_thread::get_id() << " tea161 = " << &tea161 << endl;
thread mythread2(&Teacher160::func150, &tea, tea161);
mythread2.join();
//即使使用了引用,Teacher161调用了构造函数,Teacher161还调用了 copy 构造函数,实际参数和形参依然不是一个地址
//Teacher160 构造函数
// Teacher161 构造函数 mage = 81 this_thread::getid()16348 this 000000816273F9E4
// 主线程 16348 tea161 = 000000816273F9E4
// Teacher161 copy 构造函数 this_thread::getid() = 16348 this = 000002797B7AA6D0 &obj = 000000816273F9E4
// 子线程id = 15848 & temptea = 000002797B7AA6D0
// Teacher161 析构函数被调用 this_thread::getid() = 15848
// Teacher161 析构函数被调用 this_thread::getid() = 16348
// Teacher160 析构函数
7.9传递自定义类型做参数,引用 ref
使用了ref,传递的实参和形参就是一个了
Teacher160 tea;
Teacher161 tea161(91);
cout << "主线程 " << this_thread::get_id() << " tea161 = " << &tea161 << endl;
thread mythread2(&Teacher160::func151, &tea, ref(tea161));
mythread2.join();
cout << tea161.getAge()<<endl;
Teacher160 构造函数
Teacher161 构造函数 mage = 91 this_thread::getid()13148 this 0000001D8A6FF7F4
主线程 13148 tea161 = 0000001D8A6FF7F4
子线程id = 16156 & temptea = 0000001D8A6FF7F4
89
Teacher161 析构函数被调用 this_thread::getid() = 13148
Teacher160 析构函数
三,补充,如果传递的是智能指针,要注意如果是unique_ptr,则只能 join,不能deteach,传递的时候也只能move
unique_ptr,注意要用move
class Teacher162 {
public:
void funptr(unique_ptr<int> ptr) {
cout << "子线程 id为 = " << this_thread::get_id() << " funptr *ptr = " << *ptr << " ptr = " << ptr << endl;
}
};
void main(){
///智能指针
Teacher162 tea;
unique_ptr<int> ptr(new int(20));
cout << "子线程的id = " << this_thread::get_id()<< " *ptr = " <<*ptr <<" ptr = " << ptr<< endl;
thread mythread(&Teacher162::funptr,tea,move(ptr));//注意,用的是unique_ptr,传递参数的时候,只能转移,不是copy,因此要用到move函数。。这里再复习一下一个坑点,move函数的作用是 将一个左值变成右值,本质上是调用了 移动构造函数
mythread.join();
}
shared_ptr,注意要用move
class Teacher162 {
public:
void funzhinengptr(shared_ptr<int> ptr) {
cout << "子线程 id为 = " << this_thread::get_id() << " funptr *ptr = " << *ptr << " ptr = " << ptr << endl;
}
};
void main(){
Teacher162 tea;
shared_ptr<int> ptr(new int(20));
cout << "子线程的id = " << this_thread::get_id() << " *ptr = " << *ptr << " ptr = " << ptr << endl;
thread mythread(&Teacher162::funzhinengptr, tea, ptr);//注意,用的是shared_ptr,传递参数的时候,可以copy,
mythread.join();
}
四,函数参数返回值的问题。
从前面写的例子,都没有 考虑到 线程返回值情况,这个后面再分析一下,目前想不到这个返回值在实际开发中有啥用?