C++ 内联与C inline 完全不同。
#include <iostream>
extern inline int i[];
int i [5];
struct c {
int function (){return 1;} // implicitly inline
static inline int j = 3; // explicitly inline
static int k; // without inline, a static member has to be defined out of line
static int f (){return 1;} // but a static method does not // implicitly inline
};
extern inline int b;
int b=3;
int c::k = 3; // when a static member is defined out of line it cannot have a static
// specifier and if it doesn't have an `inline` specifier in the
// declaration or on the definition then it is not inline and always
// emits a strong global symbol in the translation unit
int main() {
c j;
std::cout << i;
}
inline 本身会影响编译器、汇编器和链接器。这是对编译器的一个指令,如果它在翻译单元中使用,则只为这个函数/数据发出一个符号,如果是,那么就像类方法一样,告诉汇编器将它们存储在 .section .text.c::function(),"axG",@progbits,c::function(),comdat 或 @987654327 部分中@ 用于未初始化数据或.section .data.b,"awG",@progbits,b,comdat 用于初始化数据。模板实例化也在它们自己的 comdat 组中。
这遵循.section name, "flags"MG, @type, entsize, GroupName[, linkage]。例如,部分名称是.text.c::function()。 axG 表示该部分是可分配的、可执行的并且在一个组中,即将指定一个组名(并且没有 M 标志,因此不会指定 entsize); @progbits 表示该部分包含数据且非空白; c::function() 是组名,并且该组具有comdat 链接,这意味着在所有目标文件中,遇到带有此组名并带有 comdat 标记的所有部分都将从最终可执行文件中删除,除了 1 即编译器确保存在翻译单元中只有一个定义,然后告诉汇编器将其放在目标文件中自己的组中(1 组中的 1 节),然后链接器将确保如果任何目标文件具有同名的组,然后只在最终的 .exe 中包含一个。 inline 和不使用 inline 之间的区别现在对汇编器可见,因此链接器也可以看到,因为汇编器没有将其存储在常规的 .data 或 .text 等中,因为它们的指令。只有具有外部链接的内联符号才会被赋予像这样的外部 comdat 链接——静态链接(本地)符号不需要进入 comdat 组。
inline 在类中的非静态方法声明中,如果方法被离线定义,则使方法内联,如果在翻译单元中未引用该方法,这将防止在翻译单元中发出该方法.通过将inline 放在行外定义上可以达到相同的效果。当一个方法在没有inline 说明符的情况下被离线定义并且类中的声明不是inline 时,它将始终在翻译单元中为该方法发出一个符号,因为它将具有外部链接而不是比外部 comdat 链接。如果该方法在类中定义,则它隐式为inline,这为其提供了外部comdat 链接而不是外部链接。
static inline 在类中的成员上(与方法相反)使其成为static 成员(不涉及其链接——它具有其类的链接,可能是外部的)。 static inline 还允许在类中定义 static 类的成员,而不是需要在类中声明然后离线定义(定义中没有 static,这是不允许的-fpermissive)。 *static inline* 也使成员 inline 而不是 static inline -- inline 表示只有在翻译单元中引用定义时才会发出定义。以前,您必须在外联定义中指定 inline 才能使成员 inline。
由于static方法可以在类中定义,static inline对类中定义的static方法没有影响,它总是有外部链接,是一个静态方法,是inline。如果定义不正确,则必须使用inline 使其成为inline(即提供给外部comdat 链接而不仅仅是外部链接),并且static 仍然不能使用。
static inline 在文件范围内只影响编译器。这对编译器意味着:只有在翻译单元中使用此函数/数据时才发出一个符号,并将其作为常规静态符号(存储在 .text /.data 中,而不使用 .globl 指令)。对于汇编程序来说,static 和 static inline 现在没有区别。与inline 的其他形式一样,它不能用于class,它是一种类型,但可以用于该类类型的对象。这种形式的static inline 也不能用于函数的成员或方法,因为inline 总是被视为在类中的其他东西(这意味着该类充当范围而不是而不是作为对象的成员或方法使用)。
extern inline 是一个声明,意味着您必须在翻译单元中定义此符号,如果它被引用或抛出编译器错误;如果已定义,则将其视为常规 inline,对于汇编器和链接器,extern inline 和 inline 之间没有区别,因此这只是编译器保护。
extern inline int i[];
extern int i[]; //allowed repetition of declaration with incomplete type, inherits inline property
extern int i[5]; //declaration now has complete type
extern int i[5]; //allowed redeclaration if it is the same complete type or has not yet been completed
extern int i[6]; //error, redeclaration with different complete type
int i[5]; //definition, must have complete type and same complete type as the declaration if there is a declaration with a complete type
上面没有错误行的整个折叠到inline int i[5]。显然,如果你做了extern inline int i[] = {5};,那么extern 将被忽略,因为通过赋值进行了显式定义。
我认为 static 不允许在没有 -fpermissive 的情况下出现在 static 外线定义上的原因是因为它暗示静态引用 static 链接,因为它不是立即显而易见的程序员,它是一个类的成员,或者该类是否具有,static 意味着不同的东西。 -fpermissive 忽略了外部定义中的 static 说明符,它没有任何意义。在简单整数的情况下,k 不能在命名空间之外定义,如果 c 是命名空间,但如果 k 是函数,则无法从行中明显看出无论是在命名空间中使用static 链接的函数的外线定义,还是带有外部链接的静态成员的外线定义,都可能给程序员/读者留下错误的印象代码。
对于本地类,成员/方法上的inline 将导致编译器错误并且成员和方法没有链接。
对于命名空间上的inline,请参阅this 和this