文档目录

一、std::function 是怎么存任意可调用对象的?

std::function<int(int, int)> f = [](int a, int b) { return a + b; };
int result = f(3, 4);  // 7

你传进去的是一个 lambda(每 lambda 类型不同),但 f 能统一调用。这靠的就是 Type Erasure。

二、小对象优化(SBO)

std::function 内部有一个小缓冲区(通常是 16-32 字节):

如果可调用对象 ≤ SBO 阈值:
  ┌─────────────────────────────────┐
  │ vptr  │ 小缓冲区(存 lambda)    │  ← 栈上,无堆分配
  └─────────────────────────────────┘

如果可调用对象 > SBO 阈值:
  ┌─────────────────────────────────┐
  │ vptr  │  ptr → 堆上的 lambda    │  ← 一次堆分配
  └─────────────────────────────────┘

实测:

// 小 lambda(捕获 2 个 int,16 字节)→ SBO,无堆分配
int a = 1, b = 2;
auto small = [a, b](int x) { return a + b + x; };

// 大 lambda(捕获一个大 vector)→ 堆分配
vector<int> v(1000);
auto big = [v](int x) { return v.size() + x; };

面试题:“为什么高频构造 std::function 性能差?”

  1. 大捕获对象触发堆分配。
  2. Type Erasure 虚函数调用。
  3. std::function 的拷贝赋值运算符有引用计数的原子操作。