c++多线程2-线程参数传递需要注意的几个问题

一.线程的初始化参数需要注意以下几个问题:
1.回调函数使用引用参数接收值时,必须声明为const,否则报错;(线程基于数据安全保护的考虑)
2.回调函数必须声明为指针,才能修改实参;
3.对象隐式转换是在子线程中进行的;
4.回调函数参数为非引用时,对象的拷贝是在子线程中进行的;

二.使用detach需要注意的问题
由上四点可以发现,使用detach需要注意的问题:
1.传递对象时,建议用引用的方式进行值传递;
2.利用explicit使类不支持隐式转换;

三.数据的修改方法:
1.我们提到线程基于数据安全保护的考虑,回调函数使用引用参数接收值时,必须声明为const,否则报错;如果我们需要通过引用去传递对象时,需要用到一个函数std::ref();
2.指针传递和共享指针传递;

1.回调函数使用引用参数接收值时,必须声明为const,否则报错;(线程基于数据安全保护的考虑)
void func(const string &str) //必须声明为const
{
	cout << "func函数," << "线程id=" << std::this_thread::get_id() << ",string=" << str << endl;
}

int main()`在这里插入代码片`
{
	cout<< "main函数," << "线程id=" << std::this_thread::get_id() << endl;
	string s("hello world!");
	thread th(func, s); //对象拷贝传递
	th.join();
	return 0;
}

2.回调函数必须声明为指针,才能修改实参;
#include<iostream>
#include<thread>

using namespace std;

class Test
{
public:
	Test(int a):a_m(a)
	{
		cout << "调用Test构造函数," << "线程id:" << std::this_thread::get_id() << endl;
	}
	~Test()
	{
		cout << "调用Test析构函数," << "线程id:" << std::this_thread::get_id() << endl;
	}
private:
	int a_m;
};

void func(Test* test)
{
	cout << "func函数," << "线程id:" << std::this_thread::get_id() << endl;
}

int main()
{
	cout << "main函数," << "主线程id:" << std::this_thread::get_id() << endl;
	Test test(10);
	thread th(func, &test);//用隐式类型转化的方式
	th.join();
	return 0;
}
//打印结果
root@epc:/home/share/test#  ./test
main函数,主线程id:140712058914624
调用Test构造函数,线程id:140712058914624
func函数,线程id:140712041473792
调用Test析构函数,线程id:140712058914624
root@epc:/home/share/test# 
3.对象隐式转换是在子线程中进行的;
#include<iostream>
#include<thread>

using namespace std;

class Test
{
public:
	Test(int a):a_m(a)
	{
		cout << "调用Test构造函数," << "线程id:" << std::this_thread::get_id() << endl;
	}
	~Test()
	{
		cout << "调用Test析构函数," << "线程id:" << std::this_thread::get_id() << endl;
	}
private:
	int a_m;
};

void func(const Test& test)
{
	cout << "func函数," << "线程id:" << std::this_thread::get_id() << endl;
}

int main()
{
	cout << "main函数," << "主线程id:" << std::this_thread::get_id() << endl;
	thread th(func, 10);//用隐式类型转化的方式
	th.join();
	return 0;
}
//打印结果
root@epc:/home/share/test#  ./test
main函数,主线程id:139788677470016
调用Test构造函数,线程id:139788660029184
func函数,线程id:139788660029184
调用Test析构函数,线程id:139788660029184
root@epc:/home/share/test# 
4.回调函数参数为非引用时,对象的拷贝是在子线程中进行的;
#include<iostream>
#include<thread>

using namespace std;

class Test
{
public:
	Test(int a):a_m(a)
	{
		cout << "调用Test构造函数," << "线程id:" << std::this_thread::get_id() << endl;
	}
	Test(const Test &a)
	{
		cout << "调用Test拷贝构造函数," << "线程id:" << std::this_thread::get_id() << endl;
	}
	~Test()
	{
		cout << "调用Test析构函数," << "线程id:" << std::this_thread::get_id() << endl;
	}
private:
	int a_m;
};

void func(Test test)	//注意此处非引用
{
	cout << "func函数," << "线程id:" << std::this_thread::get_id() << endl;
}

int main()
{
	cout << "main函数," << "主线程id:" << std::this_thread::get_id() << endl;
	Test test(10);
	thread th(func, test);//用隐式类型转化的方式
	th.join();
	return 0;
}
//打印结果
root@epc:/home/share/test#  ./test
main函数,主线程id:140565759584064
调用Test构造函数,线程id:140565759584064
调用Test拷贝构造函数,线程id:140565759584064
调用Test拷贝构造函数,线程id:140565759584064
调用Test析构函数,线程id:140565759584064
调用Test拷贝构造函数,线程id:140565742143232	//在子线程进行了拷贝构造函数;
func函数,线程id:140565742143232
调用Test析构函数,线程id:140565742143232
调用Test析构函数,线程id:140565742143232
调用Test析构函数,线程id:140565759584064
root@epc:/home/share/test# 
``

1.我们提到线程基于数据安全保护的考虑,回调函数使用引用参数接收值时,必须声明为const,否则报错;如果我们需要通过引用去传递对象时,需要用到一个函数std::ref();
#include<iostream>
#include<thread>

using namespace std;

class Test
{
public:
	explicit Test(int a):a_m(a)
	{
		cout << "调用Test构造函数," << "线程id:" << std::this_thread::get_id() << endl;
	}
	~Test()
	{
		cout << "调用Test析构函数," << "线程id:" << std::this_thread::get_id() << endl;
	}
	void set(int a){a_m = a;}
	int get(){return a_m;}
private:
	int a_m;
};

void func(Test& test)
{
	cout << "func函数," << "线程id:" << std::this_thread::get_id() << endl;
	test.set(100);
}

int main()
{
	cout << "main函数," << "主线程id:" << std::this_thread::get_id() << endl;
	Test test(10);
	cout << "子线程执行前test.a_m=" << test.get() << endl;
	thread th(func, ref(test));//用隐式类型转化的方式
	th.join();
	cout << "子线程执行后test.a_m=" << test.get() << endl;
	return 0;
}
//打印结果
root@epc:/home/share/test#  ./test
main函数,主线程id:140471238637376
调用Test构造函数,线程id:140471238637376
子线程执行前test.a_m=10
func函数,线程id:140471221196544
子线程执行后test.a_m=100
调用Test析构函数,线程id:140471238637376
root@epc:/home/share/test# 
2.指针传递和共享指针传递;
#include <iostream>
#include <thread>
#include <memory>

using namespace std;

class Test
{
public:
	explicit Test(int a):a_m(a)
	{
		cout << "调用Test构造函数," << "线程id:" << std::this_thread::get_id() << endl;
	}
	~Test()
	{
		cout << "调用Test析构函数," << "线程id:" << std::this_thread::get_id() << endl;
	}
	void set(int a){a_m = a;}
	int get(){return a_m;}
private:
	int a_m;
};

void func(shared_ptr<Test> ptr)
{
	cout << "func函数," << "线程id:" << std::this_thread::get_id() << endl;
	ptr->set(100);
}

int main()
{
	cout << "main函数," << "主线程id:" << std::this_thread::get_id() << endl;
	shared_ptr<Test> test_ptr(new Test(10));
	cout << "子线程执行前test.a_m=" << test_ptr->get() << endl;
	thread th(func, test_ptr);
	th.join();
	cout << "子线程执行后test.a_m=" << test_ptr->get() << endl;
	return 0;
}
//打印结果
root@epc:/home/share/test#  ./test
main函数,主线程id:140623717164864
调用Test构造函数,线程id:140623717164864
子线程执行前test.a_m=10
func函数,线程id:140623699724032
子线程执行后test.a_m=100
调用Test析构函数,线程id:140623717164864
root@epc:/home/share/test# 
发布了32 篇原创文章 · 获赞 3 · 访问量 1413

猜你喜欢

转载自blog.csdn.net/m0_37582216/article/details/101176778