C++中的“inline” - 对于GCC和Clang/LLVM来说,这是多么强的提示?

18
在C++中,关键字“inline”有两个作用。首先,它允许定义出现在多个翻译单元中。其次,它是对编译器的提示,指示函数应该在编译后的代码中内联展开。
我的问题是:在由GCC和Clang/LLVM生成的代码中,关键字“inline”是否对函数的内联展开有任何影响?如果有,在什么情况下?还是这个提示完全被忽略了?请注意,这不是一个语言问题,而是一个与编译器相关的问题。

我同意@Ashot的观点。如果你接受问题的答案,更多的人会愿意花时间回答它。目前来看,我的回答更像是一个猜测,你可能需要一个真正的“专业”答案。 - Stephen Furlani
1
啊,我没有意识到我需要这样做,但现在我会了。 - emchristiansen
4个回答

10

[警告:我不是C++/GCC大师] 您需要了解内联函数,详情请参阅此处

对于GCC/C99,请参考这里

使用内联函数修饰符所做的建议的有效程度(C99 6.7.4)。

  • 如果使用了-fno-inline选项或使用-O0选项,则GCC不会内联任何函数。否则,由于许多原因,GCC可能仍无法内联函数;可以使用-Winline选项确定某个函数是否未被内联以及未被内联的原因。

因此,除非使用了编译器设置(如-fno-inline-O0),否则编译器将采用提示。我无法评论Clang/LLVM(或真正的GCC)。

如果这不是代码高尔夫问题并且您需要知道发生了什么,我建议使用-Winline


你还应该补充说明,文档中关于C99的内容,根据这个链接 http://gcc.gnu.org/onlinedocs/gcc/C_002b_002b-Implementation.html#C_002b_002b-Implementation ,对于C ++(g ++)也是有效的。 - UmmaGumma
@Ashot 谢谢。我对不同的标准并不是非常了解。如果你在编译时使用的不是最新的标准(如C99/GNU99或其他),你应该知道为什么。 - Stephen Furlani
链接失效通知:第一个链接现在应该 (可能) 指向 https://isocpp.org/wiki/faq/inline-functions。 - R.M.

7
一个来自gcc官网的有趣解释:内联函数和宏一样快

Some calls cannot be integrated for various reasons (in particular, calls that precede the function's definition cannot be integrated, and neither can recursive calls within the definition). If there is a nonintegrated call, then the function is compiled to assembler code as usual. The function must also be compiled as usual if the program refers to its address, because that can't be inlined.

Note that certain usages in a function definition can make it unsuitable for inline substitution. Among these usages are: use of varargs, use of alloca, use of variable sized data types (see Variable Length), use of computed goto (see Labels as Values), use of nonlocal goto, and nested functions (see Nested Functions). Using -Winline will warn when a function marked inline could not be substituted, and will give the reason for the failure.

As required by ISO C++, GCC considers member functions defined within the body of a class to be marked inline even if they are not explicitly declared with the inline keyword. You can override this with -fno-default-inline; see Options Controlling C++ Dialect.

GCC does not inline any functions when not optimizing unless you specify the `always_inline' attribute for the function, like this:

 /* Prototype.  */
 inline void foo (const char) __attribute__((always_inline)); The remainder of this section is specific

to GNU C90 inlining.

When an inline function is not static, then the compiler must assume that there may be calls from other source files; since a global symbol can be defined only once in any program, the function must not be defined in the other source files, so the calls therein cannot be integrated. Therefore, a non-static inline function is always compiled on its own in the usual fashion.

If you specify both inline and extern in the function definition, then the definition is used only for inlining. In no case is the function compiled on its own, not even if you refer to its address explicitly. Such an address becomes an external reference, as if you had only declared the function, and had not defined it.

This combination of inline and extern has almost the effect of a macro. The way to use it is to put a function definition in a header file with these keywords, and put another copy of the definition (lacking inline and extern) in a library file. The definition in the header file will cause most calls to the function to be inlined. If any uses of the function remain, they will refer to the single copy in the library.


关于最后加粗的部分,有一个问题:什么是“如果函数的使用仍然存在”的真正含义?在哪些情况下会发生这种情况? - el_technic0
@el_technic0 使用函数是调用它或获取它的地址。 - Maxim Egorushkin
我仍然不理解“大多数对函数的调用将被内联”和“任何剩余的函数使用将引用库中的单个副本”的区别。你能举出这两种不同情况的例子吗? - el_technic0
@el_technic0,我不确定我能比那段文字更清楚了。观看Chandler Carruth关于Clang优化器的视频。 - Maxim Egorushkin
好的,我猜头文件中的定义用于内联,而源(库)定义用于非内联使用。不过,需要两个相同的函数定义这一事实似乎有点丑陋。 - el_technic0

7
可以通过阅读GCC和LLVM项目的代码来收集大量信息。以下是直接从代码中获取的一些信息。(注意:这不一定是全面的,也没有列出inline在每个细节上影响内联的每种方式,它只是为了概述大部分情况。)
此信息是从2021年11月13日GCC和LLVM当前开发HEAD中收集的,因此未来可能会过时。
在GCC方面:

4

提示的强度完全取决于您使用的编译选项。大多数编译器都有选项来不进行内联,仅内联标记为“inline”的内容,或者根据最佳判断忽略提示。

最后一个选项可能效果最好。 :-)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接