inline
说明符
当 inline 说明符用于函数的 decl-specifier-seq 中时,它声明该函数为内联函数。
完全在类/结构体/联合体定义内部定义的函数,无论是成员函数还是非成员 friend 函数,都隐式地是内联函数,除非它附加到具名模块(C++20 起)。
在其首次声明中声明为 constexpr 或 consteval(C++20 起) 的函数隐式地是内联函数。 已删除的函数隐式地是内联函数:其(已删除的)定义可以出现在多个翻译单元中。 |
(C++11 起) |
当 inline 说明符用于具有静态存储期(静态类成员或命名空间作用域变量)的变量的decl-specifier-seq 中时,它声明该变量为内联变量。 在其首次声明中声明为 constexpr 的静态数据成员隐式地是内联变量。 |
(C++17 起) |
目录 |
[编辑] 解释
内联函数或内联变量(C++17 起) 具有以下属性
- 内联函数或变量(C++17 起)的定义必须在访问它的翻译单元中可访问(不一定在访问点之前)。
- 具有外部链接(例如,未声明为 static)的内联函数或变量(C++17 起)具有以下附加属性
- 程序中可以存在内联函数或变量(C++17 起)的多个定义,只要每个定义出现在不同的翻译单元中,并且(对于非静态内联函数和变量(C++17 起))所有定义都相同。 例如,内联函数或内联变量(C++17 起)可以在包含在多个源文件中的头文件中定义。
- 它必须在每个翻译单元中声明为 inline。
- 它在每个翻译单元中都具有相同的地址。
在内联函数中,
- 所有函数定义中的函数局部静态对象在所有翻译单元之间共享(它们都指向在某个翻译单元中定义的同一个对象)。
- 在所有函数定义中定义的类型在所有翻译单元中也相同。
命名空间作用域的内联 const 变量默认情况下具有外部链接(与非内联非 volatile const 限定变量不同)。 |
(C++17 起) |
inline 关键字的最初目的是作为优化器的指示符,表明函数的内联替换优先于函数调用,也就是说,不执行函数调用 CPU 指令来将控制权转移到函数体,而是执行函数体的副本而不生成调用。 这避免了函数调用(传递参数和检索结果)产生的开销,但可能会导致可执行文件更大,因为函数的代码必须重复多次。
由于内联替换在标准语义中是不可观察的,因此编译器可以自由地对任何未标记为 inline 的函数使用内联替换,并且可以自由地为任何标记为 inline 的函数生成函数调用。 这些优化选择不会更改上面列出的关于多重定义和共享静态变量的规则。
由于 inline 关键字对于函数的含义从 C++98 开始变为“允许多重定义”而不是“首选内联”,因此该含义已扩展到变量。 |
(C++17 起) |
[编辑] 注解
如果具有外部链接的内联函数或变量(C++17 起)在不同的翻译单元中定义不同,则程序是非良构的,不需要诊断。
inline 说明符不能与块作用域(另一个函数内部)的函数或变量(C++17 起)声明一起使用。
inline 说明符不能重新声明已在翻译单元中定义为非内联的函数或变量(C++17 起)。
隐式生成的成员函数和在其首次声明中声明为 defaulted 的任何成员函数都是内联的,就像在类定义内部定义的任何其他函数一样。
如果内联函数在不同的翻译单元中声明,则在每个翻译单元的末尾,累积的默认实参集合必须相同。
在 C 中,内联函数不必在每个翻译单元中都声明为 inline(最多可以有一个是非 inline 或 extern inline),函数定义不必相同(但如果程序的行为取决于调用哪个定义,则行为未指定),并且函数局部静态变量在同一函数的不同定义之间是不同的。
有关内联静态成员的其他规则,请参见静态数据成员。 内联变量消除了将 C++ 代码打包为仅头文件库的主要障碍。 |
(C++17 起) |
特性测试宏 | 值 | Std | 特性 |
---|---|---|---|
__cpp_inline_variables |
201606L |
(C++17) (C++17 起) | 内联变量 |
[编辑] 关键字
[编辑] 示例
头文件 "example.h"
#ifndef EXAMPLE_H #define EXAMPLE_H #include <atomic> // function included in multiple source files must be inline inline int sum(int a, int b) { return a + b; } // variable with external linkage included in multiple source files must be inline inline std::atomic<int> counter(0); #endif
源文件 #1
#include "example.h" int a() { ++counter; return sum(1, 2); }
源文件 #2
#include "example.h" int b() { ++counter; return sum(3, 4); }
[编辑] 缺陷报告
以下行为变更缺陷报告被追溯应用于先前发布的 C++ 标准。
DR | 应用于 | 已发布行为 | 正确行为 |
---|---|---|---|
CWG 281 | C++98 | friend 函数声明可以使用 inline 说明符 即使 friend 函数不是内联函数 |
禁止此类用法 |
CWG 317 | C++98 | 即使函数在同一翻译单元中在声明之前具有 非内联定义,也可以声明为内联 |
程序在这种 情况下是非良构的 |
CWG 765 | C++98 | 在内联函数中定义的类型可能 在不同的翻译单元中不同 |
此类类型在 所有翻译单元中是相同的 |
CWG 1823 | C++98 | 内联函数的所有定义中的字符串字面量 在所有翻译单元之间共享 |
由于一致性和实现原因, 此要求已移除 |
CWG 2531 | C++17 | 静态数据成员即使在其首次声明中 未声明为 constexpr,也可能是隐式内联的 |
在这种情况下,它不是 隐式内联的 |
[编辑] 参见
C 文档 关于 inline
|