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