在下面的代码中,我正在使用lambdas调用pthread_create类函数(可以使用函数指针完成)。前两个编译好,但第三个给出了编译错误,看起来像尝试将指向类成员的指针转换为C类函数。不确定。
#include <pthread.h>
class threadtest
{
private:
void* thread1() { return nullptr; }
void* thread2( void* p ) { return p; }
public:
void start();
};
void threadtest::start()
{
pthread_t thd0;
auto fn0 = []( void* a_pArg ) -> void* { return static_cast<threadtest*>( a_pArg )->thread1(); };
pthread_create( &thd0, NULL, fn0, (void*)this );
pthread_t thd1;
auto fn1 = []( void* a_pArg ) -> void* { void* p = nullptr; return static_cast<threadtest*>( a_pArg )->thread2( p ); };
pthread_create( &thd1, NULL, fn1, (void*)this );
pthread_t thd2;
void* p;
auto fn3 = [p]( void* a_pArg ) -> void* { return static_cast<threadtest*>( a_pArg )->thread2( p ); };
pthread_create( &thd2, NULL, fn3, (void*)this );
}
以下是错误:
threadtest.cpp: In member function ‘void threadtest::start()’:
threadtest.cpp:31:50: error: cannot convert ‘threadtest::start()::__lambda2’ to ‘void* (*)(void*)’ for argument ‘3’ to
‘int pthread_create(pthread_t*, const pthread_attr_t*, void* (*)(void*), void*)’
pthread_create( &thd2, NULL, fn3, (void*)this );
编译器版本为:gcc(Ubuntu 4.8.2-19ubuntu1)4.8.2
在我的实际代码中,我没有做第二个或第三个例子。我知道当线程访问它时,var上有一个竞争条件。我只是好奇为什么编译器在捕获任何var时会抛出错误?有什么变化?
由于
答案 0 :(得分:2)
名为fn3
的lambda表达式捕获变量p
。只有无捕获的lambdas定义了转换为函数指针。
引用N3337,§5.1.2/ 6 [expr.prim.lambda]
具有 no lambda-capture 的 lambda-expression 的闭包类型具有公共非虚拟非显式const转换函数指向函数的指针具有与闭包类型的函数调用操作符相同的参数和返回类型。此转换函数返回的值应为函数的地址,该函数在调用时与调用闭包类型的函数调用操作符具有相同的效果。
因此,当您尝试在调用pthread_create
时将lambda转换为函数指针时,它会失败。
不允许这样做的原因是函数指针无法携带lambda捕获的状态。