7-12 作用域、存储期和链接总结
作用域scope、存储期duration和链接linkage这三个概念容易引发诸多困惑,因此我们将额外安排一节课进行系统总结。其中部分内容尚未讲解,此处仅为完整性考虑及后续参考而保留。
作用域概述
标识符的作用域决定了该标识符在源代码中可被访问的位置。
-
具有块(局部)作用域
block (local) scope的变量仅可在声明点至其所在块(包括嵌套块)结尾之间被访问。这包括:- 局部变量
- 函数形参
- 在代码块内声明的程序定义类型(如枚举和类)
-
全局作用域
global scope的变量和函数可在声明点至文件结尾范围内访问,包括:- 全局变量
- 函数
- 在命名空间内或全局作用域中声明的程序定义类型(如枚举和类)
存储期概述
变量的存储期决定了其创建与销毁的时机。
- 具有自动存储期
automatic duration的变量在定义处创建,并在所属代码块结束时销毁。包括:- 局部变量
- 函数形参
- 具有静态存储期
static duration的变量在程序开始时创建,程序结束时销毁。包括:- 全局变量
- 静态局部变量
- 具有动态存储期
static duration的变量由程序员请求创建和销毁。包括:- 动态分配的变量
链接概述
标识符的链接linkage决定了在不同作用域中对同一标识符的声明是否指向同一实体(对象、函数、引用等)。
局部变量不具有链接。每个无链接的标识符声明都指向一个独特的对象或函数。
-
不具有链接
no linkage的标识符意味着相同标识符的其他声明指向独立实体。具有无作用域标识符的实体包括:- 局部变量
- 在代码块内声明的程序定义类型标识符(如枚举和类)
-
具有内部链接
internal linkage的标识符意味着相同翻译单元内相同标识符的声明指向同一对象或函数。具有内部作用域标识符的实体包括:- 静态(static)全局变量 (初始化或未初始化)
- 静态(static)函数
- 常量(const)全局变量
- 未命名的命名空间及其内部定义的任何内容
-
具有外部链接
external linkage的标识符意味着整个程序中相同标识符的声明都指向同一个对象或函数。具有外部链接的标识符实体包括:- 非静态(non-static)函数
- 非常量(non-const)全局变量(初始化或未初始化)
- 外部常量(extern const)全局变量
- 内联常量(inline const)全局变量
- 命名空间(namespace)
当外部链接标识符的定义被编译到多个.cpp文件中时,通常会引发重复定义链接错误(违反单一定义规则)。此规则存在例外情况(涉及类型、模板及内联函数/变量)——我们将在后续讲解相关主题时详细说明。
另请注意函数默认具有外部链接。可通过static关键字将其限定为内部作用域。
变量作用域、存储期与链接总结
由于变量具有作用域、存储期和链接特性,让我们通过图表进行总结:
| Type | Example | Scope | Duration | Linkage | Notes |
|---|---|---|---|---|---|
| Local variable | int x; | Block | Automatic | None | |
| Static local variable | static int s_x; | Block | Static | None | |
| Dynamic local variable | int* x { new int{} }; | Block | Dynamic | None | |
| Function parameter | void foo(int x) | Block | Automatic | None | |
| Internal non-const global variable | static int g_x; | Global | Static | Internal | Initialized or uninitialized |
| External non-const global variable | int g_x; | Global | Static | External | Initialized or uninitialized |
| Inline non-const global variable (C++17) | inline int g_x; | Global | Static | External | Initialized or uninitialized |
| Internal constant global variable | constexpr int g_x { 1 }; | Global | Static | Internal | Must be initialized |
| External constant global variable | extern const int g_x { 1 }; | Global | Static | External | Must be initialized |
| Inline constant global variable (C++17) | inline constexpr int g_x { 1 }; | Global | Static | External | Must be initialized |
前向声明概述
可通过前向声明访问其他文件中的函数或变量。声明变量的作用域遵循常规规则(全局变量为全局作用域,局部变量为块作用域)。
| Type | Example | Notes |
|---|---|---|
| Function forward declaration | void foo(int x); | Prototype only, no function body |
| Non-constant variable forward declaration | extern int g_x; | Must be uninitialized |
| Const variable forward declaration | extern const int g_x; | Must be uninitialized |
| Constexpr variable forward declaration | extern constexpr int g_x; | Not allowed, constexpr cannot be forward declared |
constexpr 变量(其隐含为 const)可通过 const 变量前向声明进行前向声明。当通过前向声明访问该变量时,该变量将被视为 const(而非 constexpr)。
存储类限定符到底是什么?
当作为标识符声明的一部分使用时,static 和 extern 关键字被称为存储类限定符storage class specifiers。在此上下文中,它们设置标识符的存储期和链接。
C++ 支持 4 种有效的存储类限定符:
| Specifier | Meaning | Note |
|---|---|---|
| extern | static (or thread_local) storage duration and external linkage | |
| static | static (or thread_local) storage duration and internal linkage | |
| thread_local | thread storage duration | |
| mutable | object allowed to be modified even if containing class is const | |
| auto | automatic storage duration | Deprecated in C++11 |
| register | automatic storage duration and hint to the compiler to place in a register | Deprecated in C++17 |
存储类限定符这一术语通常仅用于正式文档中。

浙公网安备 33010602011771号