2009-12-09 50 views

回答

7

使用inline关键字有两个原因。一个是优化提示,你可以放心地忽略它;你的编译器也喜欢忽略它。另一个原因是允许一个函数存在于多个翻译单元中,并且该用法是严格必要的。例如,如果您将函数放入.h头文件中,则最好将其声明为内联。

+1

链接不适用于C,但C++ – justin 2009-12-09 19:16:44

+0

'inline'不影响C++中的链接。 – 2009-12-09 20:14:23

+0

@litb请稍微扩展一下? – 2009-12-09 20:15:38

3

通常现代编译器会“内联”他们认为重要的东西。我会让它为你处理它。

编辑:

看完别人写的内容后,你知道吗?我想我会让它处理大部分的内联,然后剖析你的代码,然后讨论内存函数是瓶颈。我的建议是由我一起工作的某个开发人员稍微着色的,他们预先优化了他的所有代码。有一半时间我需要花费5分钟。只是搞清楚什么是要完成的。

0

您不能绝对确定编译器会捕获代码的“关键”部分:当您知道它的问题时,请使用“内联”。

编译器不是分析器。

4

编译器很聪明,但仍然可以受益于开发人员的提示。如果你认为你的某些函数应该被内联,那么就声明它们。它当然不会受伤。

+0

inline everything? ;) - 除了main()' – pmg 2009-12-09 18:52:01

+2

如果由于代码放弃导致缓存未命中,缓慢更多,因为省略函数调用开销会加快缓慢。 – hirschhornsalz 2009-12-09 19:51:06

+0

我从来没有主张过任何内容。我的意思是,如果你知道你想要一个函数内联,并且你把'inline'关键字放在它上面,那么它不会损害你内联的机会。你如何决定你想要它内联是一个完全不同的问题。 – 2009-12-09 20:39:04

2

C++ FAQ在这方面有很好的信息。我更喜欢使用内联函数,因为它为编译器提供了更多关于我会“喜欢”它的信息。编译器是否最终内联是取决于它,但给它一点帮助不会有什么影响。

0

区别不大可能重要。

离开inline直到您测量代码性能并确定您可以通过内联编译器选择正常处理的特定函数来获得某些性能。即使这样,编译器也不能保证内联函数的功能,但至少你做了所有你能做的:)

0

由于它只是编译器的一个提示,编译器可以自由地忽略它,并且可能会这样。编译器有很多你没有的相关信息,比如一个循环将占用多少缓存线,并且可以根据具体情况进行内联或不内联。

这只是一个提示,所以使用它不会伤害任何东西。你几乎肯定应该避免强制函数被内联或不内联的任何编译器特定的东西。

0

该声明几乎没有用处,与原始意图完全不同。编译器对什么以及什么不内联(IMO)有更多的自由。

这是编译器的一个暗示,使用它可以帮助你,并且有时只有预期的意义。

如果您需要编写性能关键的程序,请不要依赖编译器(了解性能&优化不会在一天中学到)。通常有一种方法可以覆盖编译器的判断(不只是暗示你的偏好),强制内联。这是我内联方式声明函数/方法的方式,超过95%的时间(也知道它何时是隐式的)。如果/当你知道你需要知道如何正确内联时,还要使用强制内联,但要确定何时以及如何使用它。

内联不是更好的性能的银弹;它可能会产生负面影响。在极端情况下,滥用内联会产生一些可怕的后果,但通常情况下性能稍差,二进制文件在使用不当时会更大。正确使用内联可以产生相当积极的结果。

内联还有助于删除否则会导出的符号,从而减少二进制数,具体取决于实例数和大小。

另一件事:你会得到与C++不同的链接。

3

与其他人一样,关键字只是一个提示,但这是一个暗示,大多数编译器都非常认真地对待。另外,大多数编译器在从不同的编译单元内联函数时都非常糟糕 - 如果您在文件a.c中定义Foo(),但将其称为b.c,则几率很小,它会智能地将b.c的调用内嵌到Foo()。 (事实上​​,没有LTCG就根本不会发生这种情况),所以当你确定一个函数真的需要内联时,这是值得使用的。这是经验时间最好的决定。

例如,在我的平台上,我测量了内联函数和直接函数(非虚函数)之间的差异约为5纳秒,所以我的经验法则是我内联的函数应该少于10个周期:平凡的访问器和类似。之后,当我的分析器告诉我在调用它们时,我浪费了大量时间。

+0

+1,指出编译器对此非常重视。 – 2009-12-10 13:48:55

0

它为编译器提供了一个简单的机制来应用更多的优化。
内联函数速度更快,因为您不需要像堆栈参数和返回地址一样将内容压入/弹出堆栈;但是,它确实会使你的二进制文件稍大一些。

它会产生显着差异吗?对于大多数人来说,在现代硬件上不够明显。但它可以有所作为,这对一些人来说已经足够了。

在线标记内容并不能保证它是内联的。这只是编译器的一个建议。有时候这是不可能的,比如当你有一个虚函数时,或者当涉及到递归时。有时编译器只是选择不使用它。 我可以看到像这样的情况,使可察觉的差异:

inline int aplusb_pow2(int a, int b) { 
    return (a + b)*(a + b) ; 
} 

for(int a = 0; a < 900000; ++a) 
    for(int b = 0; b < 900000; ++b) 
     aplusb_pow2(a, b);