C++14中从unique_ptr存储的类实例异步启动成员方法报错求助
问题修复方案
你的代码有两个核心问题导致编译失败:
- 你直接执行了
ptr->run_server(),把void类型的返回值传给了std::async,但std::async需要的是可调用对象,不是函数执行后的结果; run_server是类的私有成员,外部代码根本无权调用它。
下面是几种可行的修正方式:
方式1:用成员函数指针 + 对象指针调用
先把run_server改成public成员,然后这么写:
class foo { public: // 必须改成public才能让外部调用 void run_server() { // Do some stuff. } }; auto ptr = make_unique<foo>(); auto res = std::async(std::launch::async, &foo::run_server, ptr.get());
原理:std::async支持传入成员函数指针作为可调用对象,后面的参数必须是该成员函数所属的对象指针——这里用ptr.get()拿到unique_ptr管理的裸指针就行。注意要确保ptr的生命周期能覆盖异步线程的执行时间,别让对象提前被销毁了。
方式2:用Lambda表达式(更灵活推荐)
同样先修正run_server的访问权限,然后用Lambda包裹调用逻辑:
捕获引用(高效但需注意生命周期)
class foo { public: void run_server() { // Do some stuff. } }; auto ptr = make_unique<foo>(); auto res = std::async(std::launch::async, [&ptr]() { ptr->run_server(); });
这种方式通过引用捕获ptr,不用拷贝对象,效率更高,但一定要保证原ptr在异步线程运行期间不会被销毁或者重置。
转移所有权(线程安全)
如果担心原ptr提前失效,可以把unique_ptr的所有权转移给Lambda:
class foo { public: void run_server() { // Do some stuff. } }; auto ptr = make_unique<foo>(); auto res = std::async(std::launch::async, [ptr = std::move(ptr)]() mutable { ptr->run_server(); });
这里用std::move把ptr的所有权转移到Lambda内部,Lambda必须加mutable,不然没法修改捕获的unique_ptr(默认捕获的变量是const的)。这种方式下,异步线程里的对象生命周期由Lambda内部的ptr保证,安全性更高。
内容的提问来源于stack exchange,提问作者Dan
相关产品推荐
相关产品推荐

