C++-std::thread之向线程函数传递参数

文章目录

  • 向线程函数传递参数

向线程函数传递参数

向线程函数传递参数只需要向std::thread构造函数传递额外的参数即可

std::thread t(hello,arg1,arg2);

需要注意的是,参数会被拷贝到单独的存储空间中,然后作为右值传递给可调用对象

void f(int i,std::string const& s);
std::thread t(f,3,"hello");

这里"hello"作为const char *传递给构造函数,并且只在新线程的上下文中转换为string类型,这可能会导致某些错误:

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); 
    t.detach();
}

这里buffer作为char *类型被拷贝到内部存储空间,很有可能在buffer转化为string之前,opps函数就退出了,这时进入新线程上下文,char *被转化为string类型传递给f,此时buffer内容不确定,转为string会导致未定义的行为。

解决方案是提前转化过程:

std::thread t(f,3,std::string(buffer)); 

由于拷贝后的值是右值,如果函数参数是左值引用,那么会导致编译错误,因为不能将一个右值传递给期望左值引用参数的函数,解决方法是使用std::ref函数

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,std::ref(data)); 
    t.join();
}

当我们希望传递一个对象(这里的data)而又不拷贝它,就必须使用标准库函数ref,ref返回一个对象,包含给定的引用,此对象是可拷贝的
类似的,如果函数参数不能被拷贝只能被移动,如std::unique_ptr,那么创建线程传递参数时,如果传递进去的就是右值,那么移动相关函数会被自动调用,如果不是右值,那么需要显示调用std::move

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));

std::thread的所有权机制跟std::unique_ptr一样,虽然没有动态分配的对象,但std::thread负责管理一个线程的执行,线程的所有权可以在thread对象之间转移,但不能拷贝。这意味着一个thread对象只和一个线程关联

void hello()
{
	cout << "Hello Concurrent World!";
}

void delayHello()
{
	Sleep(3000);
	cout << "Deley Hello Concurrent World!";
}
thread t(delayHello);
thread t2(hello);
t2.join();//等待hello线程退出
t2 = std::move(t);//delayHello线程从t对象转到t2
cout << "delayHello "<<t2.joinable()<<endl;
t2.join();//等待delayHello线程退出

你可能感兴趣的:(#,CCIA,c++,后端,thread,多线程,c++11)