C++ 编译器会内联没有实体的函数吗?

C++ 编译器会内联没有实体的函数吗?,c++,C++,让我们设想一个blah.h头文件,其中包含: // A declaration without any code. We force inline __attribute__((always_inline)) void inline_func(); #include "blah.h" // The code of the inline function void inline_func() { ... } // Use the inline function void foo()

让我们设想一个blah.h头文件,其中包含:

// A declaration without any code. We force inline
__attribute__((always_inline)) void inline_func();
#include "blah.h"

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

// Use the inline function
void foo() {
    inline_func();
}
以及包含以下内容的blah.cpp源文件:

// A declaration without any code. We force inline
__attribute__((always_inline)) void inline_func();
#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中的GCC强制内联装饰
那要看情况了。在您的示例中,它将是内联的,因为函数的定义在使用它的同一翻译单元中

否则,如果没有LTO是可能的,并且在编译时函数的定义对编译器不可用,那么不,函数将不会内联

事先答复

答案是:视情况而定。它取决于编译器,也可能取决于编译器的配置

另见下文:

inline关键字的目的是作为优化器的一个指示器,表明函数的内联替换优于函数调用,也就是说,不执行调用CPU指令将控制权转移到函数体,而是执行函数体的副本,而不生成调用。这避免了函数调用复制参数和检索结果所产生的额外开销,但这可能会导致更大的可执行文件,因为函数的代码必须重复多次。 因为关键字inline的这一含义是非绑定的,所以编译器可以自由地对任何未标记为inline的函数使用inline替换,并且可以自由地生成对任何标记为inline的函数的函数调用。这些选择不会更改上面列出的关于多个定义和共享静态的规则


那要看情况了。在您的示例中,它将是内联的,因为函数的定义在使用它的同一翻译单元中

否则,如果没有LTO是可能的,并且在编译时函数的定义对编译器不可用,那么不,函数将不会内联

事先答复

答案是:视情况而定。它取决于编译器,也可能取决于编译器的配置

另见下文:

inline关键字的目的是作为优化器的一个指示器,表明函数的内联替换优于函数调用,也就是说,不执行调用CPU指令将控制权转移到函数体,而是执行函数体的副本,而不生成调用。这避免了函数调用复制参数和检索结果所产生的额外开销,但这可能会导致更大的可执行文件,因为函数的代码必须重复多次。 因为关键字inline的这一含义是非绑定的,所以编译器可以自由地对任何未标记为inline的函数使用inline替换,并且可以自由地生成对任何标记为inline的函数的函数调用。这些选择不会更改上面列出的关于多个定义和共享静态的规则


您需要在内联发生时使主体可用

即,如果您有以下文件:

inlineFunc.h
inlineFunc.c
main.c
您可以使用以下工具进行编译:

compile inline.c
compile main.c
link innline.o mcompile inline.c
编译main.c 链接innline.o main.o yourcook program.o yourcook program

inlineFunc无法在main.c中内联,但是可以内联调用inlineFunc.c中的inlineFunc

正如Paolo提到的,内联只是对编译器的一个提示,但是一些编译器也有强制内联的方法,即对于gcc,您可以使用_属性_始终u内联。在这里讨论如何处理内联

:

在这种情况下发出警告是因为未定义foo 编译main时可用。但是,使用-O2或更好的 在优化过程中,gcc执行一种向后内联,这意味着 甚至在源代码中更靠前的函数定义 文件可以嵌入到调用程序中。因此,警告 只要使用至少-O2优化,就会消失。有 是否有任何特定的选项对此行为负责?我想 即使使用-O1或-O0也可以启用向后内联


您需要在内联发生时使主体可用

即,如果您有以下文件:

inlineFunc.h
inlineFunc.c
main.c
您可以使用以下工具进行编译:

compile inline.c
compile main.c
link innline.o mcompile inline.c
编译main.c 链接innline.o main.o yourcook program.o yourcook program

inlineFunc无法在main.c中内联,但是可以内联调用inlineFunc.c中的inlineFunc

正如Paolo提到的,内联只是对编译器的一个提示,但是一些编译器也有强制内联的方法,即对于gcc,您可以使用_属性_始终u内联。在这里讨论如何处理内联

:

在这种情况下发出警告是因为未定义foo 编译main时可用。但是,使用-O2或更好的 在优化过程中,gcc执行一种反向内联,meanin G 甚至在源代码中更靠前的函数定义 文件可以嵌入到调用程序中。因此,警告 只要使用至少-O2优化,就会消失。有 是否有任何特定的选项对此行为负责?我想 即使使用-O1或-O0也可以启用向后内联


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

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

always_inline表示忽略第二步。这并不影响第一个考虑。现在,您还声明了LTO被禁用,这意味着首先要考虑的是内联能力受到限制。这表明LTO和always_inline是非常不相关的,因为它们影响两种不同的内联考虑


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

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

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

always_inline表示忽略第二步。这并不影响第一个考虑。现在,您还声明了LTO被禁用,这意味着首先要考虑的是内联能力受到限制。这表明LTO和always_inline是非常不相关的,因为它们影响两种不同的内联考虑


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

它们将与LTO内联,LTO可能会变得非常常见,并且以后可能会隐式启用。这种内联是LTO的定义,它们将与LTO内联,这可能会变得非常常见,并且可能会在以后隐式启用。这样的内联就是LTOI的定义,我用了一个非常具体的例子来描述这个问题。在该示例中,主体在实例化时是已知的。让我们坚持下去that@P.ChristopoulosCharitos:在这种情况下,我所说的关于ilineFunc.c的内容是适用的:如果主体在当时已知,那么从技术上讲可以内联。正如其他答案所述,inline关键字只是一个提示,请参阅上面的答案,了解如何强制gcc内联。在该示例中,主体在实例化时是已知的。让我们坚持下去that@P.ChristopoulosCharitos:在这种情况下,我所说的关于ilineFunc.c的内容是适用的:如果主体在当时已知,那么从技术上讲可以内联。正如其他答案所述,inline关键字只是一个提示,请参阅上面的答案,了解如何强制gcc内联。这是内联的定义。不过,这个例子有强制内联。你说得对。但是问题的标题和标签是非常一般的,所以我用一种更一般的方式来回答这个问题。这是内联的定义。不过,这个例子有强制内联。你说得对。但是问题的标题和标签都很笼统,所以我用一种更笼统的方式来回答这个问题。