应使用 std::move_only_function 存储捕获 std::unique_ptr 或 std::mutex 的 lambda,因其仅要求 MoveConstructible,而 std::function 强制 CopyConstructible 导致编译失败。

遇到捕获 std::unique_ptr 或 std::mutex 的 lambda 无法存入回调容器?直接换 std::move_only_function,别挣扎——std::function 在构造时就拒绝,不是写法问题,是语义冲突。
为什么 std::function 编译失败而 std::move_only_function 可以
错误信息通常是 error: use of deleted function 'X::X(const X&)'。这不是你的 lambda 写错了,而是 std::function 强制要求目标类型满足 CopyConstructible;一旦 lambda 捕获 std::unique_ptr,其拷贝构造函数就被隐式删除。而 std::move_only_function 只要求 MoveConstructible,绕过该限制,且不预留虚函数表或引用计数字段,实现零开销类型擦除。
- 哪怕 lambda 声明为
const,只要内部调用ptr.reset()或std::move(ptr),它就是 move-only,只能进std::move_only_function - 捕获
[&x]的 lambda 本身可能仍可拷贝,但 move 后原闭包失效,x成悬垂引用,运行时崩溃风险极高,不属于安全路径 -
std::move_only_function不支持target()或target_type(),因为 move-only 类型擦除后无法安全还原原始类型
std::move_only_function 必须显式写出完整签名
它不提供类型推导辅助,也没有 make_move_only_function,所有模板参数必须手写,包括返回类型、参数列表、noexcept、const、& 或 && 调用限定符。缺一不可,否则 operator() 行为不匹配,可能引发异常传播失控或静默调用失败。
- 正确:
std::move_only_function、std::move_only_function、std::move_only_function - 错误:
std::move_only_function(缺少括号与参数)、std::move_only_function(模板参数无法推导)、auto f = std::move_only_function{}(同样推导失败) - 捕获
std::unique_ptr的 lambda 通常需声明为mutable,否则无法在调用中移动捕获对象
所有所有权转移操作都必须显式 std::move
编译器绝不隐式转换右值,也不提供运行时兜底。漏写 std::move 就是编译失败,不是警告,不是运行时崩溃,是立刻报错。
- 初始化:
std::move_only_function,不能写f = std::move(lambda); f = lambda; - 存入容器:
std::vector<:move_only_function>> tasks;→tasks.push_back(std::move(task));,写tasks.push_back(task);直接触发use of deleted function - 函数传参:形参应声明为右值引用,如
void enqueue(std::move_only_function,调用时必须&& task) enqueue(std::move(task)); - 类成员含
std::move_only_function时,移动赋值操作符不能依赖默认生成(除非所有成员都支持移动),需显式定义为= default或逐个std::move
空值检查和调用后状态管理容易被忽略
std::move_only_function 支持空初始化(如 std::move_only_function),但调用前必须判空,否则未定义行为。而且 move 构造或 move 赋值后,源对象进入有效但未指定状态——它不为空,但不能再调用,也不能再 move,必须重新赋值或销毁。
- 调用前务必写
if (f) { f(); },不能假设非空 - move 后的原变量不能再次
std::move,也不能直接调用,否则行为未定义 - 它不是“更弱的
std::function”,而是唯一能合法收下 move-only callable 的标准容器;误用场景(比如试图塞可拷贝 lambda)反而增加冗余约束
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











