无法将调用成员函数的lambda作为C++11 thread构造参数怎么解决?
问题原因
你的代码编译失败的核心原因有两个:
- 你定义的
Foo::run函数接收的参数是无捕获的普通函数指针void (*)(),只有没有任何捕获行为的lambda才能隐式转换为这类函数指针;你写的lambda使用了[&]隐式捕获当前对象的this指针,属于带捕获的lambda,无法自动转换为普通函数指针,参数类型不匹配。 - std::thread构造时会对传入的所有参数进行拷贝/移动存储,再在新线程中调用目标函数,此时传入的lambda类型和
run要求的函数指针类型无法匹配,导致std::result_of推导失败,抛出你看到的编译错误。
可行的修改方案
该功能完全可以实现,推荐以下两种修改方式:
方案1:将run的参数改为std::function<void()>(最灵活,推荐)
std::function可以兼容所有签名匹配的可调用对象,包括带捕获的lambda,修改后代码如下:
#include <thread> #include <functional> // 新增头文件 class Foo { // 将参数类型改为std::function<void()> void run(std::function<void()> func) { func(); } void bar() { return; } void bof() { // 这里lambda显式捕获this更清晰,避免不必要的引用捕获 std::thread thread(&Foo::run, this, [this]{bar();}); thread.join(); // 必须加join或detach,否则thread析构时会触发程序终止 } };
方案2:使用无捕获lambda配合上下文透传(不需要引入std::function)
如果你坚持要使用普通函数指针作为run的参数,可以把上下文数据通过单独参数透传,实现如下:
#include <thread> class Foo { // 调整run的参数,同时接收函数指针和上下文指针 void run(void (*func)(Foo*), Foo* ctx) { func(ctx); } void bar() { return; } void bof() { // 无捕获lambda可以转换为函数指针,this作为单独参数传入 std::thread thread(&Foo::run, this, [](Foo* self){self->bar();}, this); thread.join(); } };
额外注意事项
- 你创建的std::thread对象在销毁前必须调用
join()等待线程执行结束,或者调用detach()将线程和对象解绑,否则std::thread的析构函数会直接调用std::terminate()终止程序。 - 如果你选择detach线程,一定要保证lambda捕获的this指针在线程执行期间始终有效,避免出现悬空指针访问。
内容的提问来源于stack exchange,提问作者Steve Emmerson
相关产品推荐
相关产品推荐

