仿函数真的比指向函数的指针更快吗?

Are functors actually faster than pointers to functions?

根据 Scott Meyers 的说法,C++ 优于 C 的一个方面是函数对象比函数指针更快。他说这是因为函数对象是内联的,这提高了速度。

我有两个问题:

  1. 我们如何验证函数对象实际上是内联的?我们可以在实践中验证这一点吗?

  2. 函数对象的内联是取决于我们使用的编译器,还是所有的编译器都这样?

  1. How can we verify that function objects are in fact inlined? Can we verify this in practice?

当然,检查最终发出的汇编代码。

  1. The inlining function objects depends on the compiler we use, or all compilers behave like that?

这在很大程度上取决于所使用的编译器实现和优化级别。
所以不,不能保证特定编译器(链接器)的行为如此。

虽然不能内联通过函数指针的调用。


According to him, function objects are inlined, so there is an increase in speed.

IMO "function objects are inlined" 应该更好地阅读(或听说,我不知道引用来自哪里):

function objects can be inlined while calls through function pointers cannot.

C++ 和 C 标准给编译器留下了很多自由。编译器可以在每条指令之间自由计数到 10 亿,或者仅当整数中包含质数时才这样做。

体面的 "real" 编译器不会这样做。这是实施质量问题。

将函数对象内联到 std::sort 之类的东西是每个真正的编译器都会做的事情。在这些情况下检测需要内联的内容非常容易,因为类型信息带有需要内联的代码。

使用函数指针这样做更难。使用函数指针执行此操作,其中所有内容都已转换为 void*char* 指针更难。

这样做的效果是,在实践中,对 qsort 的 C 风格调用与对 std::sort 的 C++ 风格调用相比,可以为 std::sort 带来很大的优势.

qsort 大约比 std::sort 慢 2 倍,如 here 所示,在对随机排列的整数进行排序的非常简单的情况下。

检查实际的汇编代码输出,主要是细节,小事多return。以具体的现实世界为例,您可以了解影响到底有多大。

clang、gcc 和 MSVC 的所有 3 个都能够使 std::sort 比它们的 qsort 快得多。由于这是一个简单的优化,而将函数指针优化为内联调用则不然,您可能希望在 qsort.

是的,函数对象可能会导致更快的代码。但确保这一点的唯一方法是进行基准测试。

  1. documentation 说:“GCC 可能仍然无法内联函数,原因有很多;-Winline 选项可用于确定是否一个函数没有被内联,为什么没有。"

  2. 当然这将取决于编译器、版本、标志等。有时内联会适得其反(代码膨胀等),因此每个编译器都有自己的一套规则来决定是否一个函数应该被内联。顺便说一下,inline 关键字只是一个提示,eigen 等一些库很难强制执行内联。