2012-01-03 39 views
0
class MyClass 
{ 
    public: 
     MyClass() 
     { 
      m_dbLoopStart = 0.0; 
      m_dbLoopStop = 100.0; 
      m_dbLoopStep = 0.001; 
     } 

     // Which of the following methods complete in a shorter time? 

     void Foo1() const // This one? 
     { 
      for (double x=m_dbLoopStart; x<=m_dbLoopStop; x+=m_dbLoopStep) 
      { 
       f(x); 
      } 
     } 

     void Foo2() const // Or, this one? 
     { 
      for (double x=m_dbLoopStart; x<=m_dbLoopStop; x+=m_dbLoopStep) 
      { 
       2.0 * x + 1.0; 
      } 
     } 

    private: 
     double m_dbLoopStart, m_dbLoopStop, m_dbLoopStep; 

     inline static double f(double x) 
     { 
      return 2.0 * x + 1.0; 
     } 
}; 

Foo1()Foo2()之间,哪一个会更快完成?使用内联函数与直接在代码中写入函数体一样快吗?

+5

如果完全不同,那么你需要一个更好的编译器。 – 2012-01-03 13:28:51

+1

这些都应该导致非常相似的程序集(如果不是相同的话)。 – 2012-01-03 13:28:58

+2

唯一的区别是内联函数可能不一定*被内联,而直接插入代码则编译器没有选择。 – 2012-01-03 13:31:03

回答

1

内联函数可能会更快,因为它们避免了函数调用和返回开销的代价。请记住,编译器可能会选择不内联函数。

在大多数翻译器中,必须传递函数参数并为参数和任何函数本地存储器分配空间。在返回端,函数局部变量必须被删除,通常返回一个值。

对于简单函数(如getter和setter),函数调用和返回的开销大于函数中的代码。因此内联会加快这些功能。

内联函数还会删除调用该函数的分支指令。这减少了处理器清除指令高速缓存/管道的机会。虽然现代处理器已经实现了算法来减少分支指令的负面影响。

在我的编程实践中,我内嵌小(3行或更小)的方法。如果我为了性能原因而内联,我会在内联之前进行配置。

2

如果使用内联函数,编译器可能仍然选择不复制函数本身的主体,从而导致函数调用。如果您明确写入函数体,那么肯定没有函数被调用。

从理论上讲,它的速度更快。

+8

然后,编译器实际上可能有一个不内联函数的好理由。例如,如果函数体是巨大的,则由于缓存效应,编译器可能不会内联它。现代CPU非常复杂,所以它们的性能特征并不总是直观。不内联某个特定函数可能会更快。 – 2012-01-03 13:37:29

+0

@Insilico:是的,但在这种特殊情况下,最好是内联。 – 2012-01-16 21:13:14

3

在这种情况下,使用“inline”是多余的,因为在类定义中定义的函数默认是内联的。说到这一点,将函数定义为内联并不意味着该函数必须内联,而不是将其定义为内联并不意味着编译器不会内联该函数。

正如其他人已经说过的,在这种情况下,通过优化不会有什么区别,即使循环应该优化为无代码,x被赋予m_dbLoopStop的值(无论x是什么) 。

1

将内联函数与参数调用相比,简单地使用复制/粘贴代码或#define宏常常会有轻微的语义差异。例如,考虑宏观和功能:

 
extern void some_extern_function(int x); 
#define foo1(x) (some_extern_function((x)), some_extern_function((x))) 
void inline foo2(int x) {some_extern_function(x); some_extern_function(x); } 

现在假设一个调用它们:

 
    extern volatile int some_volatile_int; 
    foo1(some_volatile_int); 
    foo2(some_volatile_int); 

在这种情况下,内联函数foo2必须做出的some_volatile_int的副本,然后通过该副本都电话some_extern_function。相比之下,宏必须加载两次some_volatile_int。根据调用约定,两种方法都可能比另一种更快。