inline 关键字
// 头文件中定义 inline 函数(多个翻译单元包含不会报重定义)
inline int square(int x) {
return x * x;
}
// C++17:inline 变量,头文件中定义全局变量不重定义
inline int g_count = 0;
// 类内定义的成员函数自动是 inline
class Foo {
public:
int get() { return val; } // 隐式 inline
private:
int val = 0;
};作用
inline 有两层含义,现代 C++ 更强调第二层:
- 建议编译器内联展开:把函数调用替换为函数体,省去调用开销。编译器可以忽略这个建议。
- 允许多重定义(ODR 豁免):同一个
inline函数/变量可以在多个翻译单元中定义,只要定义完全相同,链接器会合并为一份。这是头文件中写函数实现的标准做法。
要点
inline函数的定义必须在每个使用它的翻译单元中可见,所以通常放在头文件- 类内直接定义的成员函数隐式 inline,不需要显式写
- C++17 起支持
inline变量,解决头文件全局变量重定义问题 inline只是对编译器的建议,是否真正内联展开由编译器决定(复杂函数、递归函数通常不会展开)- 过度内联会导致代码膨胀(code bloat),反而降低缓存命中率
和 constexpr、宏对比
| 方式 | 是否类型安全 | 是否编译期求值 | 能否调试 | 典型场景 |
|---|---|---|---|---|
#define 宏 | 否 | 否(文本替换) | 否 | 旧代码兼容 |
inline 函数 | 是 | 否 | 是 | 小函数、头文件工具函数 |
constexpr 函数 | 是 | 尽量是 | 是 | 编译期常量计算 |
一句话区分:inline 解决的是链接层面的多重定义问题,内联展开只是附带效果;constexpr 解决的是编译期求值;#define 是无类型的文本替换,能不用就不用。
C 语言中的 inline(C99)
C99 引入了 inline,但语义和 C++ 不同——没有 ODR 豁免,头文件里写 inline 函数还需要在某个 .c 文件里补一个外部定义,否则链接器找不到符号。
嵌入式 C 的惯用写法是 static inline,每个翻译单元各自有一份,省去外部定义的麻烦:
// 放在 .h 文件,直接用,无需额外 .c 定义
static inline int square(int x) {
return x * x;
}HAL 库、FreeRTOS 里大量使用这个写法。纯 inline(不加 static)在 C 里反而少见。