编译器是否决定何时内联我的函数(在C ++中)?

时间:2009-07-30 07:28:03

标签: c++ compiler-theory compiler-optimization

我知道你可以使用inline关键字,或者只是将一个方法放在类声明ala short ctor或getter方法中,但编译器是否最终决定何时内联我的方法?

例如:

inline void Foo::vLongBar()
{
   //several function calls and lines of code
}

如果编译器认为它会使我的代码效率低下,它会忽略我的内联声明吗?

作为一个附带问题,如果我在我的课外宣布了一个getter方法:

void Foo::bar() { std::cout << "baz"; }

编译器是否会将其内联?

9 个答案:

答案 0 :(得分:15)

是的,是否内联代码的最终决定权在于C ++编译器。内联关键字是建议,而不是要求。

以下是有关如何在Microsoft C ++编译器中处理此决策的一些详细信息

答案 1 :(得分:10)

在一天结束时,是否内联的功能完全取决于 编译器。通常,函数在流程方面越复杂,编译器内联它的可能性就越小。而一些函数,如递归函数,根本无法内联。

不内联函数的主要原因是它会大大增加代码的整体大小,从而防止iot被保存在处理器的缓存中。这实际上是一种悲观,而不是优化。

至于让程序员决定在脚下或其他地方拍摄自己,你可以自己内联函数 - 编写功能中可能已经作为函数调用站点的代码。

答案 2 :(得分:4)

正如许多人已经发布的那样,即使您可以给出强制提示,例如forceinline,最终决定也始终取决于编译器。
部分原因是内联不是自动“快速”切换。过多的内联可能会使您的代码变得更大,并可能会干扰其他优化。请参阅The C++ FAQ Lite about inline functions and performance

答案 3 :(得分:4)

正如其他人所说,inline关键字仅仅是编译器内联代码的建议。由于编译器会定期内联未使用inline标记的代码,而不是内联代码,因此关键字似乎与register或(pre-C ++ 0x){{{ 1}}。

但是,auto关键字会影响另一件事:它将函数的链接外部(函数的默认值)更改为内联。内联链接允许每个编译单元包含它自己的目标代码副本,并使链接器从最终的可执行文件中删除冗余副本。如果这提醒您模板,是的,模板也使用内联链接。

答案 4 :(得分:3)

是的,编译器有最终决定权。 In VS you can even inline recursive functions into specified depth;)

#pragma inline_depth( [0... 255] )

答案 5 :(得分:3)

加上我的5美分......

我发现这篇关于内联的Guru of Week文章非常有用。

据我所知,我读到某个地方甚至链接器可能会内联,当它链接目标文件并发现链接的代码可以内联时。

的问候,
Ovanes

答案 6 :(得分:2)

  

作为一个附带问题,如果我在我的课外宣布了一个getter方法:

void Foo::bar() { std::cout << "baz"; }
  

编译器是否会将其内联在内?

这取决于。它可以用于同一翻译单元中的所有呼叫者(.cpp文件及其所有#included定义)。但它仍然需要编译非内联版本,因为在翻译单元之外可能存在该函数的调用者。您可以在高优化级别上看到这一点(如果您的编译器实际上可以这样做)。 (特别是:比较当你在一个.cpp中#include所有.cpp文件与典型布局时发生的情况。在一个翻译单元中的所有定义,这种内联的机会大大增加。)

答案 7 :(得分:1)

据我所知,编译器会自动创建一个你在内联声明的函数(或在类声明中写入)非内联的函数,如果它找到一个像for,while等的循环。 这是编译器在内联函数中具有最后发言权的一个示例。

答案 8 :(得分:1)

如果你真的,肯定的,绝对的,必须要内联代码,总有宏。 C多年来一直支持这些,因为在编译之前它们只是文本替换,它们确实真实地内联了你所写的内容。

这就是为什么'inline'关键字(甚至,在某些情况下,强制变体)可以承受没有标准的强制方式 - 你总是可以写一个宏。

也就是说,inline关键字通常更好,因为编译器经常知道使内联函数有意义,是因为内联可以与其余的编译器优化进行交互。