存储持续性

C++ 使用==三种==(在 C++11 中是==四种==)不同的方案来存储数据,这些方案的区别就在于数据保留在内存中的时间。

自动存储持续性

在函数定义中声明的变量(包括函数参数)的存储持续性为自动的。它们在程序开始执行其所属的函数或代码块时被创建,在执行完函数或代码块时,它们使用的内存被释放。

C++ 中有两种存储持续性为自动的变量:

  1. 自动变量(Automatic Variables)

自动变量是在函数内部(局部作用域)定义的变量。它们的生命周期与包含它们的函数的执行周期相关联。自动变量在函数入口处创建,并在函数退出时销毁。==它们通常存储在栈上==,通常,函数参数和函数内部定义的局部变量都是自动变量。

1
2
3
void exampleFunction() {
int x = 10; // 自动变量,生命周期和函数相关
}
  1. 寄存器变量(Register Variables)

寄存器变量是自动变量的一种特殊类型,它们提示编译器将其==存储在 CPU 寄存器中==,以便提高访问速度。但请注意,寄存器变量只是一种建议,编译器可以选择忽略这些建议,因为现代编译器通常能够有效地优化变量的寄存器使用。

1
2
3
void exampleFunction() {
register int x = 10; // 声明寄存器变量
}

静态存储持续性

在函数定义外定义的变量和使用关键字 static 定义的变量的存储持续性都为静态。它们在程序整个运行过程中都存在。

C++有三种存储持续性为静态的变量:

  1. 静态局部变量(Static Local Variables)

静态局部变量是在函数内部定义的,但与自动变量不同。它们的生命周期不会随着函数的调用而结束,静态局部变量只会在首次进入函数时初始化,然后一直存在于整个程序的执行过程中,直到程序退出。它们==存储在静态存储区(通常是全局数据区)==。

1
2
3
void exampleFunction() {
static int x = 10; // 静态局部变量,生命周期跨函数调用
}
  1. 静态全局变量(Static Global Variables)

静态全局变量是在全局作用域(文件作用域)内定义的变量,但它们的可见性被限制在定义它们的文件内,不能被其它文件访问。静态全局变量的生命周期与程序的运行周期相同,它们也==存储在静态存储区==。

  1. 静态类成员变量(Static Class Member Variables)

静态类成员变量是定义在类内部的静态变量,它们属于类而不是类的特例。静态类成员变量只要一份副本,无论创建多少个类的实例,它们都享有相同的变量。静态类成员变量==存储在静态存储区==。

线程存储持续性(C++11)

当前多核处理器很常见,这些 CPU 可同时处理多个执行任务。这让程序能够将计算放在可并行处理的不同线程中。如果变量是使用关键字 thread_local 声明的,则其生命周期与所属线程一样长。

动态存储持续性

new 运算符分配的内存将一直存在,直到使用 delete 运算符将其释放或程序结束为止。这种从内存的存储持续性为动态,又是被称为自由存储(free store)或==堆(heap)==。

作用域和链接性

  • 作用域(Scope):描述了名称在文件的多大范围内可见。
  • 链接性(Link):描述了名称如何在不同单元间共享。链接性为外部的名称可在文件间共享,链接性为内部的名称只能由一个文件中的函数共享。

自动存储持续性

在默认情况下,在函数中声明的函数参数和变量的==存储持续性为自动==,==作用域为局部==,==没有链接性==。如果在代码块中定义了变量,则该变量的存在时间和作用域将被限制在该代码块内。

静态持续变量

和 C 语言一样,C++ 也为静态存储持续性变量提供了 3 种链接性,且这三种链接性都在整个程序执行期间存在。

  • 外部链接性:可在其它文件中访问,必须在代码块的外部声明它。
  • 内部链接性:只能在当前文件中访问,必须在代码块的外部声明它并且使用 static 限定符。
  • 无链接性:只能在当前函数或代码块中访问,必须在代码内声明它并且使用 static 限定符。
1
2
3
4
5
6
int global = 1000; // 静态持续,外部链接
static int one_file = 50; // 静态持续,内部链接

int func1(int n) {
static in_count = 0; // 静态持续,无链接
}

所有静态持续变量都有初始化特征:未被初始化的静态变量的所有位都被设置为 0

存储描述持续性作用域链接性声明
自动自动代码块在代码块中
寄存器自动代码块在代码块中,使用关键字 register
静态,无链接性静态代码块在代码块中,使用关键字 static
静态,外部链接性静态文件外部不在任何函数内
静态,内部链接性静态文件内部不在任何函数内,使用关键字 static