问题
class background_task
{
public:
void operator()() const
{
do_something();
do_something_else();
}
};
std::thread my_thread(background_task());
my_thread.join();
编译提示错误:
request for member ‘join’ in ‘my_thread’, which is of non-class type ‘std::thread(background_task (*)())’
my_thread.join();
原因
当把函数对象传入到线程构造函数中时,如果传递了一个临时函数对象,而不是一个命名函数对象,C++编译器会将其解析为函数声明,而不是定义一个匿名对象。这就是C++‘s most vexing parse所导致的问题。
也就是说,编译器会将上面的第10行代码解析为:声明了一个名为my_thread的函数,其返回类型为std::thread,参数为一个函数指针,该函数指针指向的函数的返回类型为background_task,参数为void。即my_thread的类型为编译器所提示的:std::thread (background_task(*)()),当然没有成员函数join了。
解决办法
- 使用命名函数对象
background_task f;
std::thread my_thread(f);
- 使用多组括号
std::thread my_thread((background_task()));
- 使用新统一的初始化语法
std::thread my_thread{background_task()};
- 使用lambda表达式
std::thread my_thread([]{
do_something();
do_something_else();
});
总结
- 上述遇到的问题可以扩展到所有接收匿名函数对象为构造函数参数的对象中。