我的问题是:在由GCC和Clang/LLVM生成的代码中,关键字“inline”是否对函数的内联展开有任何影响?如果有,在什么情况下?还是这个提示完全被忽略了?请注意,这不是一个语言问题,而是一个与编译器相关的问题。
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.
inline
在每个细节上影响内联的每种方式,它只是为了概述大部分情况。)-finline-small-functions
(由-O2
暗示)和-finline-functions
(由-O2
暗示),GCC不会考虑未声明为inline
的函数进行早期内联。inline
的函数尝试内联一个被优化为大小的函数。inline
的函数略好,除非它们也在内联函数指令阈值下(即max-inline-insns-auto
,稍后将进行解释)(代码比较复杂,所以我对它的作用有点模糊)。inline
的函数将其“不良度”值除以8,这样它们会更有可能首先被内联。max-inline-insns-auto
的参数值,当函数未声明为内联时(尽管我可以看到某些情况下不是这种情况,例如当GCC的启发式算法认为“加速很大”时),此值默认为15,而在指定内联时使用max-inline-insns-single
值,默认值为70,这意味着声明为inline的函数可以内联,当它比GCC认为未声明为inline的函数大4.6倍时。 (注意:前面的超链接只是这些限制在其他地方被使用的最重要的例子)inline
且未指定-finline-small-functions
(由-O2
暗示),GCC将不会拆分函数。-finline-functions
(包含在-O2
中)时,GCC通常不会调查内联非inline
函数inline
的函数会由Clang将inlinehint
属性附加到LLVM字节码函数上inlinehint
函数的inlinehint-threshold
值,其默认值为325,否则它将使用其他内容(例如调用点是热还是冷等),如果没有找到其他内容,则将使用inlinedefault-threshold
值,默认值为225。该值与LLVM计算的启发式值进行比较,该值将计算出每个函数调用内联给定函数的成本,如果此值小于阈值,则函数将被内联,这意味着inlinehint实际上将内联函数的成本减少了约1.44,正如LLVM所看到的那样提示的强度完全取决于您使用的编译选项。大多数编译器都有选项来不进行内联,仅内联标记为“inline”的内容,或者根据最佳判断忽略提示。
最后一个选项可能效果最好。 :-)