应改用 std::move_only_function,因其仅要求 moveconstructible,支持捕获 unique_ptr 等不可拷贝资源的 lambda,且专为“移交即放弃”的异步任务设计。

遇到 error: use of deleted function 'X::X(const X&)' 就该换 std::move_only_function,不是代码写错了,是语义不匹配——它专为“移交即放弃”的异步任务设计,不能拷贝、不支持 target()、模板参数必须显式带限定符。
为什么 std::function 编译失败而 std::move_only_function 可以
因为 std::function 要求被包装类型满足 CopyConstructible;而捕获 std::unique_ptr 或 std::mutex 的 lambda 会自动禁用拷贝构造,std::function 直接拒收。但 std::move_only_function 只要求 MoveConstructible,绕过拷贝检查。
- 典型场景:异步任务持有 socket、临时 buffer、状态机对象等独占资源,复制毫无意义,还可能 double-close
- 错误不是发生在运行时,而是在构造那一刻就编译失败——没有机会“试一下”
- 即使 lambda 声明为
const,只要内部std::move了捕获对象(如mutable+std::move(ptr)),它仍是 move-only,只能进std::move_only_function
声明和初始化必须显式写出完整调用签名
std::move_only_function 没有 make_move_only_function 辅助函数,也不能靠 auto 推导模板参数。漏写任何修饰符(如 noexcept、const、&)都会导致类型不匹配。
- 正确写法:
std::move_only_function<int std::string int const noexcept></int> - 错误写法:
auto f = std::move_only_function{};(模板参数无法推导) - 错误写法:
std::move_only_function f = lambda;(缺少模板参数,编译失败) - 空初始化合法:
std::move_only_function<void> f;</void>,但调用前必须用if (f)检查是否为空
往 vector 存或传参时必须显式 std::move
所有涉及“拥有权转移”的操作,都必须手动调用 std::move。编译器不会帮你隐式移动,也不会给你运行时错误提示——直接编译失败。
-
std::vector<:move_only_function>> tasks;</:move_only_function>→tasks.push_back(std::move(task));,不能写tasks.push_back(task); - 函数参数建议用右值引用:
void enqueue(std::move_only_function<void> &&task)</void>,避免在入口就尝试拷贝 - 若封装进类成员,移动赋值操作符需显式定义为
= default或逐个std::move成员 - 别把它塞进需要
CopyConstructible的老接口(如某些第三方回调注册函数),编译不过就是不过
捕获引用时的悬垂风险容易被忽略
std::move_only_function 不是“只读”,而是“只移”。一旦 move 出去,原变量进入有效但未指定状态,再次调用会触发未定义行为。但更隐蔽的问题是:如果 lambda 捕获的是引用(如 [&x]),std::move 后原闭包仍持有悬垂引用——这不会编译报错,但运行时崩。
- 正确姿势:
auto task = std::move_only_function<void>{[handle = std::move(socket)]() mutable { handle.send("done"); }};</void> - 错误姿势:
task(); task();—— 第二次调用未定义;std::move(task)();也不行,move 后不能再调用 - 如果需要多次执行,闭包内部自己管理状态(如用
mutable+ 成员变量),而不是靠外部重复std::move - 和
std::packaged_task混用要注意:两者都消费型,但语义不同——std::packaged_task是“带 promise 的可调用体”,调用一次就释放 promise;std::move_only_function只管调用逻辑,不绑定 promise 生命周期
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











