存储期(存储持续性)
根据用于分配内存的方法,C++ 有 3 种管理数据内存的方式:自动存储、静态存储、动态存储 (有时也叫作自由存储空间或堆)。C++11 新增了第四种类型 —— 线程存储。
自动存储
在函数内部定义的常规变量使用自动存储空间,被称为自动变量。这意味着它们在所属的函数被调用时自动产生,在该函数结束时自动消亡。
实际上,自动变量是一个局部变量,其作用域为包含它的代码块。
PS:代码块是被包含在花括号中的一段代码。
自动变量通常存储在栈中,这意味着执行代码块时,这些变量依次入栈,而在离开代码块时,这些变量按照相反的顺序被释放。因此,在程序执行过程中,栈将不断增大和缩小。
静态存储
静态存储是在整个程序执行期间都存在的存储方式。
使变量称为静态的方式有两种:1. 在函数外面定义它;2. 在声明变量时使用 static 关键字。C++ 有三种存储期为静态存储的变量。
#include <iostream>
int a; // 静态存储的变量
static double b; // 静态存储的变量
void f() {
static char c; // 静态存储的变量
short d; // 自动存储的变量
}
int main (void) {
...
f();
...
}
上述代码中,变量 a、b、c 都是静态存储的变量,在程序被执行的期间一直存在,而变量 d 随着 f() 被调用而被创建,当 f() 执行完毕就会被销毁。
动态存储
new 和 delete 运算符提供了一种比自动变量和静态变量更灵活的方法。它们管理了一个内存池,这在 C++ 中被称为自由存储空间 or 堆。动态内存使用的内存池、自动变量使用的内存、静态变量使用的内存都是分开的。
与使用常规变量相比,使用 new 和 delete 让程序员对于程序如何使用内存有更大的控制权,然而,这样的代价是内存管理更加复杂。
作用域
作用域描述了名称在文件(翻译单元)中的多大范围内可见(程序可使用)。
例如,函数中定义的变量可以在该函数中使用,但不能被其他函数使用;而在文件的函数定义之前定义的变量则可以在其后的所有函数中使用。
1.局部(代码块)作用域:局部变量,变量仅在定义的代码块中可用。
2.全局(文件)作用域:全局变量,变量从定义位置开始到文件结尾之间均可用。
3.函数原型作用域:在函数原型中使用的名称只在包含参数列表的括号内可用。这也是为什么这些名称是什么以及是否出现都不重要的原因。
4.类作用域。
5.名称空间作用域:文件作用域是是名称空间作用域的特例。
void f1() {
static int a;
}
void f2() {
a++; // 报错
}
int main(void) {
f1();
f2();
}
f1() 中的变量 a 被声明为静态存储的变量,但是 a 的作用域是块作用域,即仅在 f1() 中可见。在调用 f2() 的时候,内存中虽然保存有 f1() 中的静态存储变量 a,但是对 f2() 来说 a 不可见,不能使用 a 变量。
链接性
链接性描述了名称是否可以在不同文件间共享。
链接性为外部链接的名称可以在文件间共享;链接性为内部链接的名称只能由同一个文件中的函数共享;自动变量名称不能共享,因此它们的链接性为无链接。