仿函数实际上比函数指针更快吗?

时间:2016-11-25 17:27:53

标签: c++ function-pointers function-object inlining

根据Scott Meyers的说法,C ++在C上闪耀的一个领域是函数对象比函数指针更快。他说这是因为函数对象是内联的,这会提高速度。

我有两个问题:

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

  2. 函数对象的内联是否依赖于我们使用的编译器,还是所有编译器的行为都是这样的?

3 个答案:

答案 0 :(得分:76)

C ++和C标准为编译器留下了一大堆自由。编译器可以在每条指令之间自由计数到10亿,或者只有在整数具有素数值时才能这样做。

体面"真实"编译器不这样做。这是一个实施质量问题。

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

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

这样做的结果是,在实践中,对qsort的C样式调用与对std::sort的C ++样式调用可以为std::sort带来很大的优势。 / p>

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

检查实际的汇编代码输出主要是一个细节,并且很少有回报。通过具体的实际示例,您可以了解影响的真实程度。

能够使std::sort成功的所有3个clang,gcc和MSVC明显快于qsort。由于这是一个简单的优化,虽然将函数指针优化为内联调用不是,但是您希望在qsort时,较少的主要编译器不会比这更好。

答案 1 :(得分:18)

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

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

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

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

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

  

根据他的说法,函数对象是内联的,因此速度会增加。

IMO "功能对象被内联" 应该更好地阅读(或听到,我不知道该引用来自哪里):

  
    

函数对象可以内联,而通过函数指针调用则不能。

  

答案 2 :(得分:1)

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

  1. documentation说:" 由于多种原因,GCC可能仍然无法内联函数; -Winline选项可用于确定函数是否未内联,以及为什么不。"

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