You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

探究std::function与捕获同步lambda的性能开销差异原因

为什么非模板版本的std::function性能远低于模板版本?

先看测试代码(使用GCC11 O3编译):

#include <QCoreApplication>
#include <QDebug>
#include <QElapsedTimer>
#include <QRandomGenerator>
#include <QDateTime>
#include <functional>

inline void reader(int * d, int c, std::function<void(int *)> foo) {
  while (c--) foo(d++);
}

template <class FOO>
inline void readerT(int * d, int c, FOO foo) {
  while (c--) foo(d++);
}

inline int summer(int * d, int c) {
  int s = 0;
  reader(d, c, [&s](int * dd){ s += *dd; });
  return s;
}

inline int summerT(int * d, int c) {
  int s = 0;
  readerT(d, c, [&s](int * dd){ s += *dd; });
  return s;
}

int main(int argc, char* argv[]) {
  QCoreApplication a(argc, argv);
  int tcount = 100000000;

  QVector<int> vec; vec.resize(tcount);
  QRandomGenerator gen = QRandomGenerator::securelySeeded();  
  gen.generate(vec.begin(), vec.end());

  QElapsedTimer t;
  t.restart();
  qDebug() << summer(vec.data(), tcount) << t.elapsed(); // 110 ms
  t.restart();
  qDebug() << summerT(vec.data(), tcount) << t.elapsed(); // 15 ms

  t.restart();
  int sum = 0;
  for (const auto & i : vec) { sum += i; }
  qDebug() << sum << t.elapsed(); // 15 ms

  return a.exec();
}

测试结果显示:非模板的summer函数耗时110ms,而模板版本summerT和普通循环的耗时都是15ms,性能差距悬殊。核心原因在于std::function的类型擦除机制带来的开销,以及编译器无法对其进行有效内联优化:

  • 类型擦除的间接调用开销:std::function是通用的可调用对象容器,通过类型擦除兼容任意符合签名的可调用实体(lambda、函数指针、functor等)。内部依赖虚函数表或函数指针间接调用目标函数,循环中每次foo(d++)都需要一次间接跳转,无法像模板版本那样直接内联lambda逻辑。
  • 模板的编译期具体化与内联:模板函数readerT编译时会根据传入的lambda类型生成具体实例,编译器完全知晓lambda实现细节,可直接把lambda代码内联到readerT的循环中,甚至进一步将整个readerT逻辑内联到summerT里,最终生成的机器码和普通循环几乎一致,实现“零开销”。
  • 额外的存储与内存操作:std::function可能需要为存储可调用对象分配内存(即使小对象优化,也有额外存储成本和构造/析构操作),而模板版本直接传递lambda的副本或引用,无此类额外开销。

简单来说,模板版本是编译期确定的静态分发,std::function是运行期的动态分发——后者的灵活性是以性能为代价的,需要通用兼容性时用std::function,追求极致性能时模板是更优选择。

内容的提问来源于stack exchange,提问作者dtech

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 14:47:30