使用内联函数有什么问题?

时间:2020-03-05 18:52:49  来源:igfitidea点击:

虽然在某些情况下使用内联函数会非常方便,

内联函数有什么缺点吗?

结论:

显然,使用内联函数没有错。

但是值得注意以下几点!

  • 内联的过度使用实际上会使程序变慢。根据函数的大小,对其进行内联会导致代码大小增加或者减少。内联一个非常小的访问器函数通常会减小代码大小,而内联一个非常大的函数则可以大大增加代码大小。在现代处理器上,由于更好地使用了指令高速缓存,较小的代码通常运行速度更快。 -Google指南
  • 内联函数的速度优势往往会随着函数大小的增加而减少。在某些时候,与函数主体的执行相比,函数调用的开销变小,并且失去了好处-源
  • 对于不返回任何值的函数;如果存在循环,开关或者转到语句。
  • 如果函数是递归的。 -来源
  • 仅当我们指定optimize选项时,关键字__inline才会使函数内联。如果指定了optimize,是否接受__inline取决于内联优化器选项的设置。默认情况下,只要运行优化器,内联选项就会生效。如果我们指定optimize,那么如果我们想忽略__inline关键字,还必须指定noinline选项。 -来源

解决方案

回答

我对此表示怀疑。甚至编译器也会自动内联某些函数以进行优化。

回答

可能会增加
可执行文件,我不认为
编译器将始终使
即使我们使用了
内联关键字。 (还是其他
像Vaibhav一样
说?...)

我认为通常可以
函数只有1个或者2个语句。

编辑:这是linux CodingStyle文档所说的内容:

Chapter 15: The inline disease
  
  There appears to be a common
  misperception that gcc has a magic
  "make me faster" speedup option called
  "inline". While the use of inlines can
  be appropriate (for example as a means
  of replacing macros, see Chapter 12),
  it very often is not. Abundant use of
  the inline keyword leads to a much
  bigger kernel, which in turn slows the
  system as a whole down, due to a
  bigger icache footprint for the CPU
  and simply because there is less
  memory available for the pagecache.
  Just think about it; a pagecache miss
  causes a disk seek, which easily takes
  5 miliseconds. There are a LOT of cpu
  cycles that can go into these 5
  miliseconds.
  
  A reasonable rule of thumb is to not
  put inline at functions that have more
  than 3 lines of code in them. An
  exception to this rule are the cases
  where a parameter is known to be a
  compiletime constant, and as a result
  of this constantness you know the
  compiler will be able to optimize most
  of your function away at compile time.
  For a good example of this later case,
  see the kmalloc() inline function.
  
  Often people argue that adding inline
  to functions that are static and used
  only once is always a win since there
  is no space tradeoff. While this is
  technically correct, gcc is capable of
  inlining these automatically without
  help, and the maintenance issue of
  removing the inline when a second user
  appears outweighs the potential value
  of the hint that tells gcc to do
  something it would have done anyway.

回答

函数过多的内联会增加编译后的可执行文件的大小,这可能会对缓存性能产生负面影响,但是如今,编译器自行决定对函数进行内联(取决于许多标准),而忽略inline关键字。

回答

值得指出的是,inline关键字实际上只是对编译器的提示。编译器可能会忽略内联,而只是在某个地方为该函数生成代码。

内联函数的主要缺点是它会增加可执行文件的大小(取决于实例化的数量)。在某些平台(例如嵌入式系统)上,这可能是个问题,尤其是在函数本身是递归的情况下。

我还建议使内联函数非常小。随着函数大小的增加,内联函数的速度优势趋于减少。在某些时候,与函数主体的执行相比,函数调用的开销变小,并且失去了好处。

回答

我们还应该注意,inline关键字仅是一个请求。编译器可能选择不内联它,同样,如果编译器认为速度/大小的折衷是值得的,则可以选择使未定义为内联的函数内联。

通常,该决定是基于许多因素做出的,例如在优化速度(避免调用函数)和优化大小(内联会导致代码膨胀,因此对于大型重复使用的函数而言不是很大)之间进行设置。

使用VC ++编译器,我们可以使用__forceinline来覆盖此决定。

一般而言:
如果我们确实想在标头中包含一个函数,请使用内联,但是在其他地方没有什么意义,因为如果我们要从中获取任何东西,一个好的编译器无论如何都会使其内联。

回答

我同意其他职位:

  • 内联可能是多余的,因为编译器会这样做
  • 内联可能会使代码肿

第三点是,它可能会迫使我们在标头中公开实现细节,例如,

class OtherObject;

class Object {
public:
    void someFunc(OtherObject& otherObj) {
        otherObj.doIt(); // Yikes requires OtherObj declaration!
    }
};

如果没有内联,则只需要一个OtherObject的前向声明。与内联我们
标头需要OtherObject的定义。

回答

内联较大的函数可以使程序更大,从而导致更多的高速缓存未命中并使其速度变慢。

确定函数何时足够小以内联将提高性能非常困难。 Google的C ++样式指南建议仅内联10行或者更少行的函数。

回答

正如其他人提到的那样,inline关键字只是对编译器的提示。实际上,大多数现代编译器将完全忽略此提示。编译器有自己的试探法来决定是否内联函数,并且坦率地说,我们并不需要建议,非常感谢。

如果我们确实确实想进行内联,如果我们已经对它进行了概要分析并查看了反汇编以确保重写编译器启发式方法确实有意义,那么可以这样做:

  • 在VC ++中,使用__forceinline关键字
  • 在GCC中,使用__attribute __((always_inline))

inline关键字确实具有第二个有效目的,但是在头文件中声明函数,但在类定义中声明函数。需要inline关键字来告诉编译器不要生成该函数的多个定义。

回答

一旦在头文件中定义了一个函数(即通过在类内部定义成员函数的主体隐式或者隐式地定义了内联函数),内联函数就存在问题,没有简单的方法来更改它而不用强迫用户重新编译(而不是重新链接)。通常这会引起问题,尤其是如果所讨论的函数在库中定义并且标头是其接口的一部分时,尤其如此。

回答

我不知道我的答案是否与问题有关,但:

内联虚拟方法要非常小心!一些错误的编译器(例如Visual C ++的早期版本)会为虚拟方法生成内联代码,其中标准行为除了继承树并调用适当的方法外,什么都不做。