C++的"内联" - 对GCC和Clang/LLVM有多强烈的暗示?

emc*_*sen 14 c++ gcc clang inline-code

在C++中,关键字"inline"有两个用途.首先,它允许定义出现在多个翻译单元中.其次,它提示编译器应该在编译的代码中内联函数.

我的问题:在代码由GCC和锵/ LLVM产生,并关键字"内联"有任何一个功能是否被内联轴承?如果是,在什么情况下?或者暗示完全被忽略了?请注意,这不是语言问题,而是特定于编译器的问题.

Ste*_*ani 9

[警告:不是C++/GCC大师]你想在这里阅读内联.

此外,对于GCC/C99.

使用内联函数说明符的建议的有效程度(C99 6.7.4).

  • 如果使用-fno-inline选项或使用-O0,GCC将不会内联任何函数.否则,海湾合作委员会可能由于多种原因仍然无法内联功能; -Winline选项可用于确定函数是否未内联,为什么不.

因此,除非使用您的编译器设置(如-fno-inline-O0),否则编译器会接受提示.我不能评论Clang/LLVM(或真正的GCC).

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


Max*_*kin 7

来自gcc的一个有趣的解释:内联函数与宏一样快:

由于各种原因,某些调用无法集成(特别是,无法集成函数定义之前的调用,也无法在定义中进行递归调用).如果存在非集成调用,则该函数将像往常一样编译为汇编代码.如果程序引用其地址,则必须像往常一样编译该函数,因为无法内联.

请注意,函数定义中的某些用法可能使其不适合内联替换.这些用法包​​括:使用varargs,使用alloca,使用可变大小的数据类型(请参阅可变长度),使用计算goto(请参阅标签作为值),使用非本地goto和嵌套函数(请参阅嵌套函数).当标记为内联的函数无法替换时,使用-Winline将发出警告,并将给出失败的原因.

根据ISO C++的要求,GCC认为在类的主体内定义的成员函数被标记为内联,即使它们没有使用inline关键字显式声明.您可以使用-fno-default-inline覆盖它; 请参阅控制C++方言的选项.

除非为函数指定`always_inline'属性,否则GCC不会在不优化时内联任何函数,如下所示:

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

到GNU C90内联.

当内联函数不是静态的时,编译器必须假定可能存在来自其他源文件的调用; 由于全局符号只能在任何程序中定义一次,因此不能在其他源文件中定义该函数,因此无法集成其中的调用.因此,非静态内联函数总是以通常的方式自行编译.

如果在函数定义中同时指定了inline和extern,则该定义仅用于内联.在任何情况下,函数都不会自行编译,即使您明确地引用其地址也是如此.这样的地址成为外部引用,就像您只声明了该函数一样,并且没有定义它.

内联和外部的这种组合几乎具有宏的效果.使用它的方法是将函数定义放在带有这些关键字的头文件中,并将定义的另一个副本(缺少内联和外部)放在库文件中.头文件中的定义将导致对函数的大多数调用进行内联.如果函数的任何使用仍然存在,则它们将引用库中的单个副本.


Gab*_*ier 7

通过阅读 GCC 和 LLVM 项目的代码可以收集到很多关于这方面的信息。这是通过直接阅读代码收集的一些信息。(注意:这不一定是完全全面的,也没有列出inline影响内联的每一个细节的每一种方式,它只是给出其中大部分的概述)

此信息是从 GCC 和 LLVM 截至 2021 年 11 月 13 日的当前开发 HEAD 收集的,因此将来可能不是最新的。

海湾合作委员会方面:

在 LLVM 方面:

换句话说,对于 GCC 和 Clang 来说,这看起来都是相当强烈的暗示。