拷贝
在默认情况下,参数是被拷贝进入thread的内部存储区的.且是按照右值传递给callable对象的.
void f(int i,std::string const& s);
std::thread t(f,3,"hello");
//(sai:此处"hello",是被拷贝过去的。不是引用,因为这个机制设计时要小心)
问题代码
void f(int i,std::string const& s);
void oops(int some_param)
{
char buffer[1024];
sprintf(buffer, "%i",some_param);
std::thread t(f,3,buffer); // 直接传递指针可能会导致数据未拷贝完,就已经退出作用域了.
//(sai:这个地方可能因为oops退出,而t还在拷贝buffer出现问题)
t.detach();
}
如何修复这个问题.
void f(int i,std::string const& s);
void not_oops(int some_param)
{
char buffer[1024];
sprintf(buffer,"%i",some_param);
std::thread t(f,3,std::string(buffer)); //<-- Using std::string avoids dangling pointer
//(sai:手工设计一个变量,可以避免拷贝buffer的时候oops函数退出造成crash)
t.detach();
}
传递引用数据
下面的代码并不能实现引用的作用.
void update_data_for_widget(widget_id w,widget_data& data);
void oops_again(widget_id w)
{
widget_data data;
std::thread t(update_data_for_widget,w,data); //data需要是一个movable的对象,编译器报错.
display_status();
t.join();
process_widget_data(data);
}// 编译无法通过
传递引用对象给thread
std::thread t(update_data_for_widget,w,std::ref(data)); // 这下可以编译了
//(sai:如何传递引用参数给thread对象)
传递对象的成员函数
如何传递对象函数给thread
class X
{
public:
void do_lengthy_work();
};
X my_x;
std::thread t(&X::do_lengthy_work,&my_x); // <-- 1
// (sai:如何传递对象成员函数指针给线程,注意第二参数为对象指针)
非可拷贝对象
(sai:std::unique_ptr这种类型是只能被std:move显示移动的,不能被复制。move后原来的对象变为empty)
void process_big_object(std::unique_ptr<big_object>);
std::unique_ptr<big_object> p(new big_object);
p->prepare_data(42);
std::thread t(process_big_object,std::move(p));
(sai:thread类似于unique_ptr只可以被move不可以copy)