C++语言|存储持续性、作用域和链接性
存储持续性
C++ 使用==三种==(在 C++11 中是==四种==)不同的方案来存储数据,这些方案的区别就在于数据保留在内存中的时间。
自动存储持续性
在函数定义中声明的变量(包括函数参数)的存储持续性为自动的。它们在程序开始执行其所属的函数或代码块时被创建,在执行完函数或代码块时,它们使用的内存被释放。
C++ 中有两种存储持续性为自动的变量:
- 自动变量(Automatic Variables)
自动变量是在函数内部(局部作用域)定义的变量。它们的生命周期与包含它们的函数的执行周期相关联。自动变量在函数入口处创建,并在函数退出时销毁。==它们通常存储在栈上==,通常,函数参数和函数内部定义的局部变量都是自动变量。
1 | void exampleFunction() { |
- 寄存器变量(Register Variables)
寄存器变量是自动变量的一种特殊类型,它们提示编译器将其==存储在 CPU 寄存器中==,以便提高访问速度。但请注意,寄存器变量只是一种建议,编译器可以选择忽略这些建议,因为现代编译器通常能够有效地优化变量的寄存器使用。
1 | void exampleFunction() { |
静态存储持续性
在函数定义外定义的变量和使用关键字 static 定义的变量的存储持续性都为静态。它们在程序整个运行过程中都存在。
C++有三种存储持续性为静态的变量:
- 静态局部变量(Static Local Variables)
静态局部变量是在函数内部定义的,但与自动变量不同。它们的生命周期不会随着函数的调用而结束,静态局部变量只会在首次进入函数时初始化,然后一直存在于整个程序的执行过程中,直到程序退出。它们==存储在静态存储区(通常是全局数据区)==。
1 | void exampleFunction() { |
- 静态全局变量(Static Global Variables)
静态全局变量是在全局作用域(文件作用域)内定义的变量,但它们的可见性被限制在定义它们的文件内,不能被其它文件访问。静态全局变量的生命周期与程序的运行周期相同,它们也==存储在静态存储区==。
- 静态类成员变量(Static Class Member Variables)
静态类成员变量是定义在类内部的静态变量,它们属于类而不是类的特例。静态类成员变量只要一份副本,无论创建多少个类的实例,它们都享有相同的变量。静态类成员变量==存储在静态存储区==。
线程存储持续性(C++11)
当前多核处理器很常见,这些 CPU 可同时处理多个执行任务。这让程序能够将计算放在可并行处理的不同线程中。如果变量是使用关键字 thread_local
声明的,则其生命周期与所属线程一样长。
动态存储持续性
用 new
运算符分配的内存将一直存在,直到使用 delete
运算符将其释放或程序结束为止。这种从内存的存储持续性为动态,又是被称为自由存储(free store)或==堆(heap)==。
作用域和链接性
- 作用域(Scope):描述了名称在文件的多大范围内可见。
- 链接性(Link):描述了名称如何在不同单元间共享。链接性为外部的名称可在文件间共享,链接性为内部的名称只能由一个文件中的函数共享。
自动存储持续性
在默认情况下,在函数中声明的函数参数和变量的==存储持续性为自动==,==作用域为局部==,==没有链接性==。如果在代码块中定义了变量,则该变量的存在时间和作用域将被限制在该代码块内。
静态持续变量
和 C 语言一样,C++ 也为静态存储持续性变量提供了 3 种链接性,且这三种链接性都在整个程序执行期间存在。
- 外部链接性:可在其它文件中访问,必须在代码块的外部声明它。
- 内部链接性:只能在当前文件中访问,必须在代码块的外部声明它并且使用
static
限定符。 - 无链接性:只能在当前函数或代码块中访问,必须在代码内声明它并且使用
static
限定符。
1 | int global = 1000; // 静态持续,外部链接 |
所有静态持续变量都有初始化特征:未被初始化的静态变量的所有位都被设置为 0。
存储描述 | 持续性 | 作用域 | 链接性 | 声明 |
---|---|---|---|---|
自动 | 自动 | 代码块 | 无 | 在代码块中 |
寄存器 | 自动 | 代码块 | 无 | 在代码块中,使用关键字 register |
静态,无链接性 | 静态 | 代码块 | 无 | 在代码块中,使用关键字 static |
静态,外部链接性 | 静态 | 文件 | 外部 | 不在任何函数内 |
静态,内部链接性 | 静态 | 文件 | 内部 | 不在任何函数内,使用关键字 static |