让我们想象一个包含以下内容的blah.h头文件:
#include "blah.h"
// The code of the inline function
void inline_func() {
...
}
// Use the inline function
void foo() {
inline_func();
}
包含以下内容的blah.cpp源文件:
inline_func()
问题是,编译器是否实际内联inline_func()
?代码应该与声明一起使用还是可以分开?
答案 0 :(得分:2)
内联分为两个步骤: * 可能吗? *值得吗?
第一步相当简单地由编译器决定,第二步是更复杂的启发式。因此,仅考虑可能的优化的好处是有意义的。
always_inline
表示忽略第二步。它不会影响第一个考虑因素。现在,您还表示LTO已被禁用,这意味着首先考虑的内联能力受到限制。这表明LTO
和always_inline
非常不相关,因为它们会影响两种不同的内联注意事项。
不管LTO对你的例子是否重要。正在考虑的两项职能属于同一翻译单位。似乎没有其他限制,例如递归,库调用或其他可观察的副作用。这意味着应该可以内联,并且因为这是唯一的考虑因素,所以应该内联。
答案 1 :(得分:1)
嗯,这取决于。在您的示例中,它将被内联,因为函数的定义位于使用它的相同转换单元中。
否则,如果没有LTO是可能的,并且在编译时编译器无法使用该函数的定义,那么不会,该函数将不会内联。
事先答复
答案是:这取决于。这取决于编译器,它也可能依赖于编译器的配置(1) (2)。
另请参阅inline description at cppreference.com(引用如下):
inline关键字的意图是作为优化器的指示器,该函数的内联替换优先于函数调用,即而不是执行调用CPU指令以将控制转移到函数体,执行函数体的副本而不生成调用。这避免了函数调用(复制参数和检索结果)所产生的额外开销,但它可能导致更大的可执行文件,因为函数的代码必须重复多次。 由于关键字内联的这种含义是非约束性的,编译器可以自由地使用内联替换任何未标记为内联的函数,并且可以自由地生成对内联标记的任何函数的函数调用 。这些选择不会改变有关上面列出的多个定义和共享静态的规则。
答案 2 :(得分:1)
在内联应该发生的时候,你需要让身体可用。
即。如果您有以下文件:
inlineFunc.h
inlineFunc.c
main.c
你编译:
compile inline.c
compile main.c
link innline.o mcompile inline.c
编译main.c 链接innline.o main.o yourCoookProgramain.o yourCoookProgram
inlineFunc
无法main.c
内联,但inlineFunc
中对inlineFunc.c
的调用可以内联。
正如Paolo所提到的,inline
只是对编译器的暗示,但是一些编译器也有办法强制内置,即对于gcc,你可以使用__attribute__(always_inline)
。请点击此处讨论gcc如何处理内联。
在这种情况下发出警告,因为foo()的定义不是 编译main()时可用。但是,使用-O2或更好 优化,gcc执行一种“向后内联”,意思是 甚至在源中进一步领先的函数定义 文件可以嵌入到调用者中。因此,警告 一旦使用至少-O2优化就会消失。在那儿 任何特定的选项负责这种行为?我想要 即使使用-O1或-O0也能启用“向后内联”。