2.2向线程函数传递参数(C++并发编程实战)

向std::thread构造函数中可调用对象或函数传递一个参数很简单,需要注意的是:默认参数要拷贝到线程独立内存中,即使参数是引用的形式

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

函数第二个参数需要进行隐式转换。

当指向动态变量的指针作为参数传递给线程的情况:

void f(int i,std::string const& s);
void oops(int some_param)
{
	char buffer[1024];	//1
	sprintf(buff,"%i",some_param);
	std::thread t(f,3,buffer);	//2
	t.detach()
}

这种情况下,buffer(1)是一个指针变量,然后通过buffer传递到新线程中(2),函数很有可能在字面值转换成std::string对象之前(oops)崩溃,从而导致未定义行为。想要依赖隐式转换将字面值转换成std::string对象,但因std::string的构造函数会复制提供的变量,有可能只复制了没有转换成功的字面值。

解决方法:在传递给std::string构造函数之前就将字面值转化为std::string对象:

void f(int i,std::string const& s);
void oops(int some_param)
{
	char buffer[1024];	//1
	sprintf(buff,"%i",some_param);
	std::thread t(f,3,std::string(buffer));	//使用std::string,避免悬垂指针
	t.detach()
}

如果你想期望传递一个引用,可以使用std::ref将参数转换成引用形式。(即使你第二个参数传递的是引用,std::thread的构造函数并不知晓传入的函数指针第二个参数是引用;构造函数无视函数期待的参数类型,并盲目的拷贝已提供的变量。)

对于std::thread和std::bind而言都可以传递体格成员函数指针作为线程函数,并提供一个合适的对象指针作为第一个参数:

class X
{
public:
	void do_length_work();
};
X my_x;
std::thread(&X::do_length_work,&my_x);	//1

这段代码中,新线程将my_x.do_length_work作为线程函数;my_x的地址作为指向对象提供给函数,也可以为成员函数提供参数,std::thread第三个参数就是成员函数的第一个参数,以此类推。

但是提供的成员函数的参数可以移动,但不能拷贝。当原对象是一个临时对象,自动进行移动操作,但当原对象是命名变量,那么转移的时候就需要使用std::move进行显示移动。下面展示的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::move,big_object对象的所有权就被首先转移到新创建的线程的内部存储了,之后传递给process_big_object函数。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值