将函数声明为“内联”的好处?
每当我读到C中的“内联”声明时,都会提到它只是编译器的一个提示 (即它不必遵守它)。 那么添加它有什么好处,还是我应该依赖编译器比我更了解?
使用inline
关键字有两个原因。 一个是优化提示,你可以放心地忽略它; 你的编译器也想忽略它。 另一个原因是允许函数存在于多个翻译单元中,并且这种使用是非常必要的。 例如,如果将函数放入.h头文件中,则最好将其声明为内联函数。
编译器很聪明,但仍然可以从开发人员的提示中受益。 如果您认为某些特定function应该被内联,那么就这样声明它们。 这当然没有伤害。
通常,现代编译器将“内联”他们认为重要的事物。 我会让它为你处理它。
编辑:
看完别人写的东西后,你知道吗? 我想我会让它处理大部分内联THEN配置你的代码和那些是瓶颈的内联函数。 我的建议稍微有点像我和他一起工作的某个开发人员,他预先优化了他的所有代码。 有一半的时间我需要花5分钟。 只是搞清楚要完成什么。
就像其他人所说的那样,关键字只是一个提示,但这是大多数编译器非常重视的暗示。 此外,大多数编译器在内联不同编译单元的函数方面都非常糟糕 – 如果你在文件ac
定义Foo()
,但是在bc
调用它,那么它很可能会智能地内联bc
对Foo()
的调用。 (事实上,如果没有LTCG,它就不会发生。)所以当你确定一个函数真的需要内联时,它是值得使用的。 这是一个最佳的经验时机决策。
例如,在我的平台上,我测量了内联和直接(非虚拟)函数之间的差异大约5纳秒,所以我的经验法则是我内联函数应该花费不到十个周期:简单的访问器等。 当我的探查器告诉我,我在调用它们的开销上浪费了很多时间后,其他特定function会被内联。
C ++ FAQ有很好的信息。 我更喜欢使用内联函数,因为它为编译器提供了更多关于我“喜欢”它的信息。 编译器是否最终内联它取决于它,但给它一点帮助不会受到伤害。
您不能完全确定编译器将捕获代码的“关键”部分:当您知道它很重要时使用“内联”。
编译器不是分析器。
差异不太重要。
保持inline
直到您测量代码性能并确定您可以通过内联编译器选择正常处理的特定函数来获得一些性能。 即使这样,也无法保证编译器会内联该function,但至少你做了所有你能做到的:)
由于它只是对编译器的一个提示,编译器可以自由地忽略它,并且可能会。 编译器有许多您没有的相关信息,例如循环将占用多少缓存行,并且可以根据具体情况内联或不内联。
这只是一个提示,所以使用它不会有任何伤害。 您几乎肯定应该避免任何强制函数内联或不内联的特定于编译器的事物。
声明几乎没用,与原始意图完全不同。 编译器已经采取了更多的自由,而不是内联(IMO)。
这是对编译器的一个提示,使用它会对你有所帮助并且有时只有预期的意义。
如果您需要编写性能关键程序,请不要依赖编译器(不会在一天内学习性能和优化知识)。 通常有一种方法可以覆盖编译器的判断(不只是暗示你的偏好),强制内联。 这是我在内部声明函数/方法的方式,超过95%的时间(也知道它是隐式的)。 如果/当你知道你需要知道如何正确内联时,那么也应该使用强制内联,但是要知道何时以及如何使用它。
内联不是提高性能的灵丹妙药; 它可能会产生负面影响。 在极端情况下滥用内联可能会产生一些可怕的后果,但通常表现稍差,如果使用不当,二进制文件会更大。 正确使用内联可以产生相当积极的结果。
内联还有助于删除否则将导出的符号,从而减少二进制文件,具体取决于实例和大小的数量。
另一件事:你会得到与C ++不同的联系。
它为编译器提供了一种应用更多OPTIMIZATIONS的简单机制。
内联函数更快,因为您不需要像在参数和返回地址上那样在堆栈上推送和弹出内容; 但是,它确实使你的二进制文件略大。
它有显着差异吗? 在大多数现代硬件上并不明显。 但它可以产生影响,这对某些人来说已经足够了。
标记内联内容并不能保证它是内联的。 这只是对编译器的建议。 有时它不可能,例如当你有虚函数或者涉及递归时。 有时编译器只选择不使用它。 我可以看到这样的情况产生了可检测的差异:
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);