C++11多线程 - Part 3: 为线程传递参数

翻译:https://thispointer.com//c11-multithreading-part-3-carefully-pass-arguments-to-threads/

为了给一个线程相关联的调用对象或函数传递参数,仅仅只需要在std::thread构造时传递额外的参数。
默认情况下,所有参数都被复制到新线程的内部存储中。

让我们看一个例子:

在C++11中将普通参数传递给std::thread

#include <iostream>
#include <string>
#include <thread>
void threadCallback(int x, std::string str)
{
	std::cout << "Passed Number = " << x << std::endl;
	std::cout << "Passed String = " << str << std::endl;
}
int main()
{
	int x = 10;
	std::string str = "Sample String";
	std::thread threadObj(threadCallback, x, str);
	threadObj.join();
	return 0;
}
/*输出结果
Passed Number = 10
Passed String = Sample String
*/

在C++11中如何将参数不传递给线程

不要将本地栈中的变量地址传递给线程的回调函数。因为线程1中的局部变量可能超出范围,但线程2仍试图通过其地址访问它。
在这种情况下,访问无效地址可能会导致意外行为,例如:

#include <iostream>
#include <thread>
void newThreadCallback(int * p)
{
	std::cout<<"Inside Thread :  "" : p = "<<p<<std::endl;
	std::chrono::milliseconds dura( 1000 );
	std::this_thread::sleep_for( dura );
	*p = 19;
}
void startNewThread()
{
	int i = 10;
	std::cout<<"Inside Main Thread :  "" : i = "<<i<<std::endl;
	std::thread t(newThreadCallback,&i);
	t.detach();
	std::cout<<"Inside Main Thread :  "" : i = "<<i<<std::endl;
}
int main()
{
	startNewThread();
	std::chrono::milliseconds dura( 2000 );
	std::this_thread::sleep_for( dura );
	return 0;
}

/*输出结果:
Inside Main Thread :   : i = 10
Inside Thread :   : p = 0x7ffeefbf49cc
Inside Main Thread :   : i = 10
*/

在C++11中如何将引用传递给std::thread

因为参数被复制到新的线程栈中,如果你需要以通用方式传递引用,例如:看看这个

#include <iostream>
#include <thread>
void threadCallback(int const & x)  // 常量传参,线程会将参数拷贝后访问, 这里必须用const,不然会报错
{
	int & y = const_cast<int &>(x);
	y++;
	std::cout<<"Inside Thread x = "<<x<<std::endl;
}
int main()
{
	int x = 9;
	std::cout<<"In Main Thread : Before Thread Start x = "<<x<<std::endl;
	std::thread threadObj(threadCallback, x);
	threadObj.join();
	std::cout<<"In Main Thread : After Thread Joins x = "<<x<<std::endl;
	return 0;
}

/*输出结果
In Main Thread : Before Thread Start x = 9
Inside Thread x = 10
In Main Thread : After Thread Joins x = 9
*/

即使threadCallback接受引用作为参数,但在线程外部仍然看不到所做的更改。
这是因为线程函数threadCallback中的x引用了复制到新线程堆栈中的临时值。
如何修改,使用std::ref()

#include <iostream>
#include <thread>
void threadCallback(int const & x) // 可以不使用const
{
	int & y = const_cast<int &>(x);
	y++;
	std::cout<<"Inside Thread x = "<<x<<std::endl;
}
int main()
{
	int x = 9;
	std::cout<<"In Main Thread : Before Thread Start x = "<<x<<std::endl;
	std::thread threadObj(threadCallback,std::ref(x));
	threadObj.join();
	std::cout<<"In Main Thread : After Thread Joins x = "<<x<<std::endl;
	return 0;
}

/*输出结果
In Main Thread : Before Thread Start x = 9
Inside Thread x = 10
In Main Thread : After Thread Joins x = 10
*/

将指向类的成员函数的指针作为线程函数

将指向成员函数的指针作为回调函数传递,将指向对象的指针作为第二个参数传递。
例如:

#include <iostream>
#include <thread>
class DummyClass {
public:
	DummyClass(){}

	DummyClass(const DummyClass & obj){}
	void sampleMemberFunction(int x)
	{
		std::cout<<"Inside sampleMemberFunction "<< x << std::endl;
	}
};
int main() {
	DummyClass dummyObj;
	int x = 10;
	std::thread threadObj(&DummyClass::sampleMemberFunction,&dummyObj,x);
	threadObj.join();
	return 0;
}

/*输出结果
Inside sampleMemberFunction 10
*/
posted on 2020-04-15 17:46  JJ_S  阅读(830)  评论(0编辑  收藏  举报