C++并发编程(CH02)[ 传递参数-02]

拷贝

在默认情况下,参数是被拷贝进入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)

发布了127 篇原创文章 · 获赞 11 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/luixiao1220/article/details/104612422