作用域、存储期与链接汇总

由于“作用域、存储期、链接”三个概念常常造成混淆,本课对它们进行系统梳理。下文部分内容尚未在前文展开,仅作完整性与未来参考之用。

作用域(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

存储类说明符是什么?

在标识符声明中,staticextern 关键字被称为存储类说明符。在此上下文中,它们设置标识符的存储期链接

C++ 支持 4 个活跃的存储类说明符:

说明符含义备注
extern静态(或 thread_local)存储期,外部链接
static静态(或 thread_local)存储期,内部链接
thread_local线程存储期
mutable即使包含类为 const,对象仍允许修改

以下说明符已废弃:

  • auto:自动存储期(C++11 起废弃)
  • register:自动存储期及寄存器提示(C++17 起废弃)

术语“存储类说明符”通常仅见于正式文档。

关注公众号,回复"cpp-tutorial"

可领取价值199元的C++学习资料

公众号二维码

扫描上方二维码或搜索"cpp-tutorial"