inline
说明符
当在函数的声明说明符序列中使用inline说明符时,它将函数声明为内联函数。
在类/结构体/联合体定义中完整定义的函数,无论是成员函数还是非成员friend函数,都隐式地是内联函数,除非它附加到具名模块(C++20 起)。
首次声明时被声明为constexpr或consteval(C++20 起)的函数隐式地是内联函数。 已删除的函数隐式地是内联函数:其(已删除的)定义可以出现在多个翻译单元中。 |
(C++11 起) |
当在具有静态存储期的变量(静态类成员或命名空间作用域变量)的声明说明符序列中使用inline说明符时,它将变量声明为内联变量。 首次声明时被声明为constexpr的静态数据成员隐式地是内联变量。 |
(C++17 起) |
目录 |
[编辑] 解释
内联函数或内联变量(C++17 起)具有以下属性
- 内联函数或变量(C++17 起)的定义必须在访问它的翻译单元中可达(不一定在访问点之前)。
- 具有外部链接的内联函数或变量(C++17 起)(例如,未声明为static)具有以下附加属性
- 程序中可以有内联函数或变量(C++17 起)的多个定义,只要每个定义出现在不同的翻译单元中,并且(对于非静态内联函数和变量(C++17 起))所有定义都相同。例如,内联函数或内联变量(C++17 起)可以在头文件中定义,该头文件被包含在多个源文件中。
- 它必须在每个翻译单元中都声明为inline。
- 它在每个翻译单元中具有相同的地址。
在一个内联函数中,
- 所有函数定义中的函数局部静态对象在所有翻译单元之间共享(它们都引用在一个翻译单元中定义的同一个对象)。
- 所有函数定义中定义的类型在所有翻译单元中也是相同的。
命名空间作用域下的内联 const 变量默认具有外部链接(与非内联非 volatile const 限定变量不同)。 |
(C++17 起) |
inline关键字的最初意图是作为优化器的指示符,表明函数内联替换优于函数调用,也就是说,不是执行函数调用CPU指令将控制权转移到函数体,而是执行函数体的副本,而无需生成调用。这避免了函数调用产生的开销(传递参数和获取结果),但由于函数代码必须重复多次,可能会导致可执行文件更大。
由于内联替换在标准语义中是不可观察的,编译器可以自由地对任何未标记为inline的函数使用内联替换,并可以自由地对任何标记为inline的函数生成函数调用。这些优化选择不会改变上述关于多重定义和共享静态的规则。
由于C++98以来,函数关键字inline的含义变成了“允许多个定义”而不是“优先内联”,因此该含义也扩展到变量。 |
(C++17 起) |
[编辑] 注意
如果具有外部链接的内联函数或变量(C++17 起)在不同的翻译单元中定义不同,则程序是格式错误的,不需要诊断。
inline说明符不能用于块作用域(在另一个函数内部)中的函数或变量(C++17 起)声明。
inline说明符不能重新声明已在翻译单元中定义为非内联的函数或变量(C++17 起)。
隐式生成的成员函数和任何在首次声明时被声明为默认的成员函数都像在类定义中定义的任何其他函数一样是内联的。
如果内联函数在不同的翻译单元中声明,则在每个翻译单元的末尾,累积的默认参数集必须相同。
在C语言中,内联函数不必在每个翻译单元中都声明为inline(最多一个可以是非inline或extern inline),函数定义不必相同(但如果程序依赖于调用哪个函数,则行为未指定),并且函数局部静态变量在同一函数的不同定义之间是不同的。
有关内联静态成员的附加规则,请参阅静态数据成员。 内联变量消除了将C++代码打包为仅头文件库的主要障碍。 |
(C++17 起) |
功能测试宏 | 值 | 标准 | 特性 |
---|---|---|---|
__cpp_inline_variables |
201606L |
(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++ 标准。
缺陷报告 | 应用于 | 发布时的行为 | 正确的行为 |
---|---|---|---|
CWG 281 | C++98 | 友元函数声明可以使用 inline 说明符 即使友元函数不是内联函数 |
禁止此类用法 |
CWG 317 | C++98 | 即使函数在声明之前在同一翻译单元中有一个非内联定义,也可以将其声明为内联 定义在同一翻译单元中,也可以将其声明为内联 |
程序格式错误 在这种情况下,枚举是病态的 |
CWG 765 | C++98 | 内联函数中定义的类型可能 在不同的翻译单元中不同 |
此类类型在所有翻译单元中都相同 在所有翻译单元中都相同 |
CWG 1823 | C++98 | 内联函数的所有定义中的字符串字面量 在所有翻译单元之间共享 |
由于一致性和实现原因,该要求被删除 一致性和实现原因 |
CWG 2531 | C++17 | 即使静态数据成员在首次声明时未声明为constexpr,它也可以隐式内联 它在首次声明时未声明为constexpr |
在这种情况下它不是隐式内联的 在这种情况下 |
[编辑] 另请参阅
C 文档,关于 inline
|