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
*/