由于“作用域、存储期、链接”三个概念常常造成混淆,本课对它们进行系统梳理。下文部分内容尚未在前文展开,仅作完整性与未来参考之用。
作用域(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 起废弃)
术语“存储类说明符”通常仅见于正式文档。