由于“作用域、存储期、链接”三个概念常常造成混淆,本课对它们进行系统梳理。下文部分内容尚未在前文展开,仅作完整性与未来参考之用。
作用域(Scope)汇总
标识符的作用域决定其在源代码中的可访问范围。
- 块(局部)作用域 
 仅在声明点起至所在代码块结束(含嵌套块)内可见:- 局部变量
- 函数形参
- 在块内声明的自定义类型(如枚举、类)
 
- 全局作用域 
 从声明点起至文件结束均可见:- 全局变量
- 函数
- 在命名空间或全局范围内声明的自定义类型(如枚举、类)
 
存储期(Duration)汇总
变量的存储期决定其创建与销毁时机:
- 自动存储期 
 定义点创建,离开所属代码块即销毁:- 局部变量
- 函数形参
 
- 静态存储期 
 程序启动时创建,程序结束时销毁:- 全局变量
- 静态局部变量
 
- 动态存储期 
 由程序员显式请求创建与销毁:- 动态分配变量
 
链接(Linkage)汇总
标识符的链接决定在不同作用域中同名声明是否指向同一实体(对象、函数、引用等)。
- 无链接 
 每个同名声明指向唯一实体:- 局部变量
- 在块内声明的自定义类型标识符(枚举、类等)
 
- 内部链接 
 同一翻译单元内同名声明指向同一实体:- static全局变量(无论是否初始化)
- static函数
- const全局变量
- 匿名命名空间及其内部所有定义
 
- 外部链接 
 整个程序范围内同名声明指向同一实体:- 非 static函数
- 非 const全局变量(无论是否初始化)
- extern const全局变量
- inline const全局变量
- 命名空间
 
- 非 
具有外部链接的实体若被编译进多个 .cpp 文件,通常会触发链接器“重复定义”错误(违反一次定义规则)。类型、模板、内联函数/变量等例外情形将在后续课程介绍。
此外,函数默认具有外部链接,可使用 static 关键字改为内部链接。
变量作用域、存储期与链接一览表
| 类型 | 示例 | 作用域 | 存储期 | 链接 | 备注 | 
|---|---|---|---|---|---|
| 局部变量 | int x; | 块 | 自动 | 无 | |
| 静态局部变量 | static int s_x; | 块 | 静态 | 无 | |
| 动态局部变量 | int* x{ new int{} }; | 块 | 动态 | 无 | |
| 函数形参 | void foo(int x) | 块 | 自动 | 无 | |
| 内部非 const 全局变量 | static int g_x; | 全局 | 静态 | 内部 | 可初始化或保留未初始化 | 
| 外部非 const 全局变量 | int g_x; | 全局 | 静态 | 外部 | 可初始化或保留未初始化 | 
| C++17 内联非 const 全局变量 | inline int g_x; | 全局 | 静态 | 外部 | 可初始化或保留未初始化 | 
| 内部常量全局变量 | constexpr int g_x{ 1 }; | 全局 | 静态 | 内部 | 必须初始化 | 
| 外部常量全局变量 | extern const int g_x{ 1 }; | 全局 | 静态 | 外部 | 必须初始化 | 
| C++17 内联常量全局变量 | inline constexpr int g_x{ 1 }; | 全局 | 静态 | 外部 | 必须初始化 | 
前向声明汇总
利用前向声明可在其他文件中访问函数或变量。变量的作用域依旧遵循常规规则(全局变量全局作用域,局部变量块作用域)。
| 类型 | 示例 | 说明 | 
|---|---|---|
| 函数前向声明 | void foo(int x); | 仅提供原型,无函数体 | 
| 非常量变量前向声明 | extern int g_x; | 必须未初始化 | 
| const变量前向声明 | extern const int g_x; | 必须未初始化 | 
| constexpr变量前向声明 | extern constexpr int g_x; | 不允许, constexpr不能前向声明 | 
constexpr 变量(隐式 const)可借助 const 变量前向声明实现;通过此声明访问时,变量被视为 const 而非 constexpr。
存储类说明符是什么?
在标识符声明中,static 与 extern 关键字被称为存储类说明符。在此上下文中,它们设置标识符的存储期与链接。
C++ 支持 4 个活跃的存储类说明符:
| 说明符 | 含义 | 备注 | 
|---|---|---|
| extern | 静态(或 thread_local)存储期,外部链接 | |
| static | 静态(或 thread_local)存储期,内部链接 | |
| thread_local | 线程存储期 | |
| mutable | 即使包含类为 const,对象仍允许修改 | 
以下说明符已废弃:
- auto:自动存储期(C++11 起废弃)
- register:自动存储期及寄存器提示(C++17 起废弃)
术语“存储类说明符”通常仅见于正式文档。
