03C++11多线程编程之测试join,detach传各种实参时形参的拷贝次数

03C++11多线程编程之测试join,detach传各种实参时形参的拷贝次数

首先我们看下面的总结测试图,然后一步步的测试。
在这里插入图片描述

1 这里我们先测试join传实参的类型
当实参为普通对象时:

1)当形参为普通对象时,拷贝了两次。
在这里插入图片描述

2)当形参为引用时:拷贝了一次。
在这里插入图片描述

3)当形参为指针时:无拷贝。
在这里插入图片描述

当实参为临时对象时:

1)形参为值时,拷贝了两次。
在这里插入图片描述
2)形参为引用时,拷贝了一次,并且在主线程拷贝构造完毕。
在这里插入图片描述
3)当形参为指针时:无拷贝。
在这里插入图片描述
当实参为引用时:

1)当形参为普通对象时:拷贝一次。
在这里插入图片描述
2)当形参为引用时:无拷贝。
在这里插入图片描述

3)当形参为指针时:无法传参。

thread mytobj(MyPrint, std::ref(a));//error
thread mytobj(MyPrint, &std::ref(a));//error

2 detach传实参的类型测试
当实参为普通对象时:

1)当形参为普通对象时:拷贝两次。
在这里插入图片描述
2)当形参为引用时:拷贝一次。
在这里插入图片描述
3)当形参为指针时:无拷贝,并且多次执行非法访问m_i,打印的值为未确定值,非常危险,禁用。
在这里插入图片描述

当实参为临时对象时:

1)当形参为普通对象时:拷贝两次。这里注意一下:它每次输出结果都是正确的,即10,但是因为线程打印次序有时很乱,导致1和0错开。但是你打断点查看每次都是10。
在这里插入图片描述

2)当形参为引用时:拷贝一次,并且如果你多次运行,发现它每次都是在主线程执行完毕就已经拷贝构造完成。这个方法也是最安全的传参方法。
在这里插入图片描述

3)当形参为指针时:无拷贝,并且禁用,多次运行会出现未知的值。
可以看到,没有值是因为主线程已经结束了,线程与屏幕脱离关系。所以就导致指针再访问就出现问题。
在这里插入图片描述

当实参为引用时:

1)当形参为普通对象时:拷贝一次。危险操作。
在这里插入图片描述

2)当形参为引用时:无拷贝。危险操作。
在这里插入图片描述
3)当形参为指针时:无拷贝。危险操作,万万不能使用。并且传参失败。

thread mytobj(MyPrint, std::ref(a));//error
thread mytobj(MyPrint, &std::ref(a));//error

3 给出代码,自己一步步的安装上面传参即可,不要偷懒

#include<iostream>
#include<thread>
#include<string>

using namespace std;

class A{
public:
	mutable int m_i;

public:
	//类型转换构造函数,可以把一个int转换成一个类A对象。
	A(int a) :m_i(a){
		cout << "A::A(int a)构造函数执行!" << this << "threadid:" << std::this_thread::get_id() << endl;
	}

	A(const A &a) :m_i(a.m_i){
		cout << "A::A(A &a)复制构造函数执行!" << this << "threadid:" << std::this_thread::get_id() << endl;
	}

	~A(){
		cout << "A::~A()析构函数执行!" << this << "threadid:" << std::this_thread::get_id() << endl;
	}

	void thread_work(int num){
		cout << "子线程thread——work执行!" << this << "threadid:" << std::this_thread::get_id() << endl;
	}
};

//形参a
void MyPrint(const A a) {
	cout << "I am A" << endl;

	//打印多行是方便测试指针在主线程结束在线程非法访问m_i
	//cout << "I am A" << endl;
	//cout << "I am A" << endl;
	//cout << "I am A" << endl;
	//cout << "I am A" << endl;
	cout << a->m_i << endl;
}


int main(){
	
	//实参为thread参数2
	A a(10);
	thread mytobj(MyPrint, a);
	mytobj.join();

	return 0;
}

4 终极总结上面join和detach如何传参
下面这四点上一篇文章也总结过了。

  • 1)int型的直接值传递。
  • 2)指针绝不使用。
  • 3)传递类对象时,形参为引用,实参为匿名对象。形参为引用是防止多次拷贝,实参为匿名对象是防止子线程拷贝之前主线程提前结束。
  • 4)使用join上面问题均不出现。
  • 5)了解各种传参时的拷贝次数,拷贝次数看上图。

学完本篇,你可以熟练掌握线程如何传参。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值