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