0Pricing
C++ Academy · 课时

std::function:类型擦除的可调用对象

通过 std::function 擦除类型,并理解小型缓冲区优化

std::function:类型擦除的可调用对象 是 CoddyKit 上的免费 C++ Academy 课时。 这是第 4 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 C++ Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 C++ Academy 课程共包含 4 节课。

问题:一种类型容纳多种可调用对象

每个 Lambda 表达式都有唯一类型。每个函数指针也有不同的类型。我们需要一种能够容纳它们的统一类型——std::function。

模板参数

std::function<Signature> 接受返回类型和参数类型。只要签名匹配,它就能接受任何可调用对象。

#include <functional>
std::function<int(int, int)> op;
op = [](int a, int b) { return a + b; };
std::cout << op(3, 4);   // 7

存储不同的可调用对象

同一个 std::function 变量可以存储 Lambda 表达式、函数指针或函子,只要签名匹配即可。

std::function<int(int)> f;
f = [](int x) { return x * 2; };       // lambda
f = ::abs;                              // function pointer
f = std::negate<int>{};                  // functor

类型擦除

在内部,std::function 使用类型擦除:它可以存储任何可调用对象,并通过统一接口隐藏其真实类型。通常还会进行一次小型堆分配。

性能代价

通过 std::function 调用时会涉及间接调用(类似于虚函数)。这比直接调用 Lambda 表达式更慢。请避免在性能关键路径中使用。

何时使用 std::function

在以下情况下可以使用它:

  • 将回调存储在容器或类成员中
  • 从函数返回可调用对象
  • 构建插件或事件系统

空的 std::function

默认构造的 std::function 是空的。调用它会抛出 std::bad_function_call。

std::function<void()> f;
if (f) f(); else std::cout << "no callback set";

成员函数指针

请使用 std::bind 绑定成员函数,或者将其包装在 Lambda 表达式中。

struct Obj { void greet(int) {} };
Obj o;
std::function<void(int)> cb = [&](int n) { o.greet(n); };

与函数指针比较

函数指针无法存储状态。std::function 可以,但代价是进行间接调用。

与模板比较

带有可调用对象参数的模板会在编译期进行特化,速度最快。std::function 在运行时解析,速度较慢但更加灵活。

template <typename F>
void run(F f) { f(); }            // compile-time, no overhead

void run(std::function<void()> f) { f(); }   // runtime, type erasure

C++23 中的 std::function:std::function_ref

C++23 增加了 std::function_ref,它是可调用对象的非拥有型视图。当生命周期有明确边界时,它可以避免堆分配。

替代方案

还有一些轻量级替代方案:std::move_only_function(C++23)、tl::function_ref 和 folly::Function。请根据需求进行选择。

快速检查

std::function 的主要缺点是什么?

总结

std::function<Signature> 可以存储任何签名匹配的可调用对象。它适用于回调、插件以及可调用对象的运行时多态,但代价是进行间接调用。

常见问题解答

「std::function:类型擦除的可调用对象」课时是免费的吗?

是的 — 「std::function:类型擦除的可调用对象」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 C++ Academy 课程的其余内容,请升级到 CoddyKit PRO。 C++ Academy 课程共包含 4 节课。

「std::function:类型擦除的可调用对象」这节课中我会学到什么?

通过 std::function 擦除类型,并理解小型缓冲区优化 你通过在浏览器中直接运行的动手代码来练习 C++ Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 C++ Academy 需要有经验吗?

无需任何先前经验。CoddyKit 上的 C++ Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 4 节课,共 4 节。

「std::function:类型擦除的可调用对象」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 C++ Academy 课中编写并运行代码吗?

能。每节 C++ Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. 函数对象与仿函数
  2. Lambda 按值、按引用捕获与 mutable
  3. 泛型 Lambda 与闭包(C++14)
  4. std::function:类型擦除的可调用对象
← 返回 C++ Academy