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