c++ c++26 function_ref c++如何使用轻量级函数引用

幻夢星雲

幻夢星雲

2026-04-14

771人浏览

原创

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

c++ c++26 function_ref c++如何使用轻量级函数引用

absl::FunctionRef 是什么,和 std::function 有什么区别

它不是标准库组件,而是 Abseil 提供的轻量级非拥有式函数引用。absl::FunctionRef 不拷贝、不分配内存、不管理生命周期,只保存一个指针(或两个)加一个调用器函数指针,大小固定为 16 字节(x64)。而 std::function 是所有权型封装,会 deep-copy 可调用对象,可能触发堆分配,尤其对捕获较多状态的 lambda 来说开销明显。

常见错误现象:用 const std::function& 作参数传入高频调用函数(如遍历回调),结果 profiler 显示大量 malloc 和虚函数调用开销——其实只需换成 absl::FunctionRef 就能消除。

  • 适用场景:作为函数参数接收回调,尤其是性能敏感路径(如容器算法、事件分发、序列化钩子)
  • 不适用场景:需要长期持有、跨作用域存储、或需复制给多个消费者时(此时应选 absl::AnyInvocablestd::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 构造函数接受右值,但内部不延长其生命周期)。

C函数速查手册(CHM版)
C函数速查手册(CHM版)

C函数速查手册(CHM版)

下载
  • 正确写法: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_refabsl::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++ 的入门与实战技巧!

相关文章

c++速学教程(入门到精通)
c++速学教程(入门到精通)

c++怎么学习?c++怎么入门?c++在哪学?c++怎么学才快?不用担心,这里为大家提供了c++速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

c++

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
c语言const用法
c语言const用法

const是关键字,可以用于声明常量、函数参数中的const修饰符、const修饰函数返回值、const修饰指针。详细介绍:1、声明常量,const关键字可用于声明常量,常量的值在程序运行期间不可修改,常量可以是基本数据类型,如整数、浮点数、字符等,也可是自定义的数据类型;2、函数参数中的const修饰符,const关键字可用于函数的参数中,表示该参数在函数内部不可修改等等。

2023.09.20

1128

7

string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

2023.08.02

2959

3

int占多少字节
int占多少字节

int占4个字节,意味着一个int变量可以存储范围在-2,147,483,648到2,147,483,647之间的整数值,在某些情况下也可能是2个字节或8个字节,int是一种常用的数据类型,用于表示整数,需要根据具体情况选择合适的数据类型,以确保程序的正确性和性能。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.08.29

1709

6

c++怎么把double转成int
c++怎么把double转成int

本专题整合了 c++ double相关教程,阅读专题下面的文章了解更多详细内容。

2025.08.29

1676

10

C++中int的含义
C++中int的含义

本专题整合了C++中int相关内容,阅读专题下面的文章了解更多详细内容。

2025.08.29

745

10

javascriptvoid(o)怎么解决
javascriptvoid(o)怎么解决

javascriptvoid(o)的解决办法:1、检查语法错误;2、确保正确的执行环境;3、检查其他代码的冲突;4、使用事件委托;5、使用其他绑定方式;6、检查外部资源等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2023.11.23

536

5

java中void的含义
java中void的含义

本专题整合了Java中void的相关内容,阅读专题下面的文章了解更多详细内容。

2025.11.27

207

13

lambda表达式
lambda表达式

Lambda表达式是一种匿名函数的简洁表示方式,它可以在需要函数作为参数的地方使用,并提供了一种更简洁、更灵活的编码方式,其语法为“lambda 参数列表: 表达式”,参数列表是函数的参数,可以包含一个或多个参数,用逗号分隔,表达式是函数的执行体,用于定义函数的具体操作。本专题为大家提供lambda表达式相关的文章、下载、课程内容,供大家免费下载体验。

2023.09.15

464

5

python lambda函数
python lambda函数

本专题整合了python lambda函数用法详解,阅读专题下面的文章了解更多详细内容。

2025.11.08

278

7

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
RabbitMQ 教程手册
RabbitMQ 教程手册

共0课时 | 0人学习

Linux man-pages 项目
Linux man-pages 项目

共0课时 | 0人学习

C# 教程
C# 教程

共94课时 | 20.2万人学习