2015-07-01 48 views
1

让我们想象一下,包含blah.h头文件:编译器是否会在没有主体的情况下内联函数?

// A declaration without any code. We force inline 
__attribute__((always_inline)) void inline_func(); 

而且包含blah.cpp源文件:

#include "blah.h" 

// The code of the inline function 
void inline_func() { 
    ... 
} 

// Use the inline function 
void foo() { 
    inline_func(); 
} 

的问题是,将编译器实际上内联inline_func()?代码应该与声明一起使用,还是可以分开使用?

  • 假设没有LTO
  • 注意在inline_func()
+4

他们将与LTO内联,这可能会变得非常平常(也许稍后会隐式启用)。 **这种内联是LTO的定义** –

回答

1

您需要在内联应该发生时提供正文。

I.e.如果你有下列文件:

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

没有办法inlineFuncmain.c中得到内联,但可以内联inlineFunc.c中的inlineFunc

正如Paolo提到的,inline只是编译器的一个提示,然而一些编译器也有办法强制inining,即对于gcc你可以使用__attribute__(always_inline)。请在这里讨论gcc如何处理内联。

An interesting sitenote

编译主()时

警告在这种情况下,foo的定义出具()不是 可用。但是,使用-O2或更好的优化时,gcc会执行一种“反向内联”,意思是 甚至可以将源文件中更进一步的函数定义嵌入到调用者中。因此,一旦使用至少-O2优化,警告 就会消失。是否有 任何特定的选项负责此行为?我想 即使使用-O1或-O0启用“反向内联”。

+0

我用一个非常具体的例子来描述这个问题。在这个例子中,身体在实例化时是已知的。让我们坚持到 –

+0

@ P.ChristopoulosCharitos:在这种情况下我说过'ilineFunc.c'适用:如果身体里的时候知道这在技术上是可能的内联。正如其他答案所述,'inline'关键字仅仅是一个提示,请参阅上面的答案,了解如何强制gcc进行内联。 – ted

1

井(GCC)力直列装饰,它依赖。在你的例子中,它将被内联,因为函数的定义与它使用的翻译单元位于同一个翻译单元中。否则,如果没有LTO是可能的,并且在编译时该函数的定义对编译器不可用,则不,该函数将不被内联。


此前答案

答案是:这取决于。这取决于编译器,它也可能取决于编译器的配置(1)(2)

参见inline description at cppreference.com(以下引用):

inline关键字的意图是作为指示器,以该函数的内联取代优于函数调用优化,即,代替执行调用CPU指令以将控制转移到功能体,则执行功能体的副本而不产生呼叫。这样可以避免由函数调用(复制参数和检索结果)所产生的额外开销,但可能会导致更大的可执行文件,因为函数的代码必须重复多次。 由于关键字内联的这种含义不具有约束力,因此编译器可以自由使用内联替换来对内联未标记的任何函数进行内联替换,并且可自由生成对内联标记的任何函数的函数调用。这些选择不会改变上述多个定义和共享静态的规则。

+0

这是内联的定义。该示例强制内联。 –

+0

你说得对。但问题标题和标签非常普遍,所以我以更一般的方式得到了问题。 –

2

内联是一个两步过程: *是否有可能? *这是否值得?

第一步相当简单的由编译器决定,第二步是更复杂的启发式。因此,只考虑可能的优化的好处是有意义的。

always_inline意味着第二步被忽略。它不影响首先考虑。现在,您也已经声明LTO已被禁用,这意味着首先考虑内联功能的限制。这表明LTOalways_inline是非常不相关的,因为它们影响两种不同的内联注意事项。

无论如何,LTO并不重要。正在审议的两项职能在同一翻译股。似乎没有其他限制,例如递归,库调用或其他可观察的副作用。这意味着应该可以内联,因为这是唯一的考虑因素,所以应该内联。

相关问题