absl::functionref是非拥有式轻量函数引用,仅存指针与调用器、大小固定16字节;而std::function是拥有式封装,会深拷贝并可能堆分配。

absl::FunctionRef 是什么,和 std::function 有什么区别
它不是标准库组件,而是 Abseil 提供的轻量级非拥有式函数引用。absl::FunctionRef 不拷贝、不分配内存、不管理生命周期,只保存一个指针(或两个)加一个调用器函数指针,大小固定为 16 字节(x64)。而 std::function 是所有权型封装,会 deep-copy 可调用对象,可能触发堆分配,尤其对捕获较多状态的 lambda 来说开销明显。
常见错误现象:用 const std::function& 作参数传入高频调用函数(如遍历回调),结果 profiler 显示大量 malloc 和虚函数调用开销——其实只需换成 absl::FunctionRef 就能消除。
- 适用场景:作为函数参数接收回调,尤其是性能敏感路径(如容器算法、事件分发、序列化钩子)
- 不适用场景:需要长期持有、跨作用域存储、或需复制给多个消费者时(此时应选
absl::AnyInvocable或std::function) - 兼容性:要求 C++17 起,Abseil v20230802 或更新;GCC 9+、Clang 10+、MSVC 19.28+ 均可正常编译
如何正确声明和调用 absl::FunctionRef
声明语法是 absl::FunctionRef<returntype></returntype>,注意括号里是完整函数签名,不是类型别名。调用方式与普通函数完全一致,无额外语法负担。
示例中容易踩的坑:把 absl::FunctionRef<void></void> 写成 absl::FunctionRef<void></void>(漏掉括号),编译器报错信息模糊,实际是模板实参不匹配;或者误传临时 lambda 给非 const 引用参数(absl::FunctionRef 构造函数接受右值,但内部不延长其生命周期)。
- 正确写法:
void Process(absl::FunctionRef<int int> op)</int> - 可安全传入:
Process([](int a, int b) { return a + b; });(lambda 是纯右值,FunctionRef只存其地址) - 不可靠写法:
auto f = [&cnt](int a) { cnt++; }; Process(f);—— 若f是局部变量且在Process返回后销毁,后续调用将 UB - 若需捕获局部变量并长期使用,请改用
absl::AnyInvocable并确保其生存期覆盖调用点
C++26 标准版 function_ref 还没落地,别混淆
目前(2026 年 4 月)C++26 标准尚未发布,std::function_ref 仍未进入标准库。网上部分文章提到的 “C++26 引入 std::function_ref” 实为误传——委员会确实在讨论类似提案(P0794R9),但截至 C++26 功能冻结节点(2025 年 Q1),该特性未被正式纳入。当前所有可用的 function_ref 都来自第三方:Abseil 的 absl::FunctionRef、Trompeloeil 的 trompeloeil::function_ref,或社区头文件实现(如 tl::function_ref)。
你如果看到编译错误提示 “‘function_ref’ is not a member of ‘std’”,不是你配置错了,是标准还没它。强行启用实验性标志(如 GCC 的 -fconcepts 加自定义头文件)风险高,不建议用于生产环境。
- 检查是否误用了命名空间:写
std::function_ref而非absl::FunctionRef - 确认 Abseil 已正确链接:头文件路径包含
absl/functional/function_ref.h,且链接了absl::base等依赖目标 - 避免混用不同实现:
tl::function_ref和absl::FunctionRef接口相似但 ABI 不兼容,不能相互转型
替代方案选型:什么时候该用 AnyInvocable 而不是 FunctionRef
核心判断依据只有一个:是否需要转移所有权。如果回调要被存储、复制、或跨线程传递,absl::FunctionRef 就不够用了——它不保证底层可调用对象的生存期。
例如实现一个异步任务队列,用户注册回调后主线程立即返回,后台线程稍后执行:这时必须用 absl::AnyInvocable,因为它支持移动构造,能接管 lambda 捕获的栈变量或堆资源;而 FunctionRef 在这种场景下极易引发 use-after-free。
-
absl::FunctionRef:适合“即用即弃”的短时回调,比如std::for_each的第三个参数 -
absl::AnyInvocable:适合需要 move 语义、生命周期管理、或可能多次调用的场合 - 性能差异:两者构造成本接近,但
AnyInvocable的析构可能触发释放逻辑,FunctionRef析构是空操作 - 注意:C++26 的
std::move_only_function(已定稿)行为更接近AnyInvocable,但它仍不等于FunctionRef
FunctionRef 前,先问一句:这个 lambda 的捕获变量,在我调用它的时候,还活着吗?C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











