

新闻资讯
技术学院std::function_ref 是零开销、非拥有、类型擦除的只读回调视图,内部仅存 void* 和函数指针,不分配内存、不复制可调用体,但不管理生命周期,误用将导致悬垂引用或未定义行为。
很多人看到 std::function_ref 就以为它是类似 int& 那样的原生引用,其实完全不是。它不持有任何对象,也不参与所有权管理,只是一个轻量级的、非拥有的、类型擦除的回调视图。它的核心目标是:在不分配内存、不复制可调用体的前提下,把任意可调用物(lambda、函数指针、std::function、绑定对象等)统一接入同一接口。
普通引用要求编译期知道具体类型,而回调场景往往需要“接受多种可调用类型”的统一参数签名。比如一个日志函数想同时接受 void()、void(int)、const char*() 等不同签名的可调用体——这无法用单个模板参数 T& 实现,因为每个 T 都是不同类型,函数重载或模板推导会爆炸。
std::function_ref 可绑定 []{}、&my_free_func、std::function、甚至捕获了局部变量的 lambda(只要不逃逸)auto&& f 或 const auto& f 虽然也能转发,但无法作为函数参数统一声明;写成模板又导致实例化膨胀std::function 会触发堆分配(除非小对象优化生效),且拷贝有开销;std::function_ref 完全避免这两点它内部只存两个字段:一个指向可调用体的 void*(或类似指针),一个指向调用分发函数的函数指针。两者加起来通常就是 16 字节(x64),且所有操作都是纯指针解引用 + 间接跳转,无虚函数表、无 new/delete、无异常传播开销。
void example(std::function_refcb) { int result = cb(3.14); // 直接调用,无额外分支或检查 }
cb 内部存储的是其地址 + 编译器生成的静态调用桩cb 存储的是捕获块地址 + 对应的调用桩(该桩由标准库为每种签名生成一次)std::function,cb 仅借用其存储区和调用逻
辑,不复制内容std::function_ref 不延长所引用对象的生命期——若传入栈上 lambda 并保存其 function_ref 到作用域外,就是悬垂引用最典型的坑是把它当成“轻量版 std::function”来长期持有回调。它没有所有权语义,也没有移动/拷贝构造的安全保障(拷贝是浅复制,移动未定义)。
立即学习“C++免费学习笔记(深入)”;
std::function_ref 成员变量存进类里,除非你 100% 控制被引用对象的生命周期长于该类std::function_ref,除非返回的是全局函数或静态 lambdastd::function_ref{[]{}}() —— 临时对象在表达式结束就销毁,引用立刻悬垂nullptr 检查(没有空状态),也不能赋值(只有构造)