# 内存分区 1. 栈区(stack):指那些由编译器在需要的时候分配,不需要时⾃动清除的变量所在的存储区,效率高,分配的内存空间有限,形参和局部变量分配在栈区,栈是向地地址生长的数据结构,是一块连续的内存。 2. 堆区(heap):由程序员控制内存的分配和释放的存储区,是向高地址生长的数据结构,是不连续的存储空间,堆的分配(malloc)和释放(free)有程序员控制,容易造成二次删除和内存泄漏。 3. 静态存储区(static):存放全局变量和静态变量的存储区,初始化的变量放在初始化区,未初始化的变量放在未初始化区。在程序结束后释放这块空间。 4. 常量存储区(const):存放常量字符串的存储区,只能读不能写,const修饰的全局变量存储在常量区(取决于编译器),const修饰的局部变量在栈区。 5. 程序代码区:存放源程序二进制代码。 # 内存存储类型 ## 一、自动存储 在函数内部定义的常规变量使用的为自动存储空间,称为自动变量(automatic variable),它们在调用时自动产生,在该函数结束时消亡。自动变量属于局部变量,作用域为包含的代码块。自动变量通常存储在栈中,其中变量在程序执行过程中依次加入到栈中,在离开代码块时将按相反的顺序释放这些变量。后进先出(LIFO),在程序执行过程中,栈的大小不断变化。 自动存储持续性。在函数中声明的变量的存储持续性为自动的,它们在函数或者代码块被执行的时候创建,在执行完函数或者代码块后就自动释放内存空间。 ## 二、静态存储 静态存储时整个程序执行期间都存在的存储方式。使变量成为静态变量的方式有两种:一种是在函数外定义它;另一种是在声明变量时使用关键字static。例如:`static double fee = 56.50` 。自动存储的自动变量和静态存储的静态变量严格地限制了变量的寿命,静态变量存在与整个程序运行的生命周期。 静态存储持续性。在函数外定义的变量和使用关键字 `static` 定义的变量存储持续性都为静态,它们在程序运行的整个生命周期内都存在。静态存储不需要栈结构,是一块独立的存储区域。C++为静态存储持续性提供了3种链接性。 - 外部链接性(可在其他文件中访问):在代码块外部声明 - 内部链接性(只能在当前文件中访问):在代码块外部声明,且用`static` 限定符 - 无链接性(只能在当前函数和代码块中访问):在代码块内部声明,且用`static` 限定符 ```C++ int global = 1000; //变量global是一个具有外部链接性的静态存储(static duration, external linkage) static int oneFile = 50; //变量oneFile是一个具有内部链接性的静态存储(static duration, internal linkage) int main(){ ... } void function1(int n){ static int count = 0; int a = 0; } //变量count是一个无链接性的静态存储(static duration, no linkage) //注意这三个变量global、oneFile和count在程序执行期间都存在 ``` | 存储描述 | 持续性 | 作用域 | 链接性 | 声明方式 | | ---------------- | ------ | ------ | ------ | -------------------------------- | | 自动 | 自动 | 代码块 | 无 | 在代码块中 | | 寄存器 | 自动 | 代码块 | 无 | 在代码块中,使用关键字register | | 静态,无链接性 | 静态 | 代码块 | 无 | 在代码块中,使用关键字static | | 静态,外部链接性 | 静态 | 文件 | 外部 | 不在任何函数内 | | 静态,内部链接性 | 静态 | 文件 | 内部 | 不在任何函数内,使用关键字static | ## 三、动态存储 `new` 和`delete` 运算符提供了比自动变量和静态变量更为灵活的方法。他们管理了一个内存池,成为堆(heap)或者自由存储空间(free store)。堆区和栈区是完全分开的。堆区数据存储的生命周期不完全受程序或函数的执行控制,内存管理有时会非常复杂,在栈区自动添加和删除机制使得占用的内存总是连续的,而在堆区主要由两个运算符决定。 动态存储持续性。用`new` 运算符分配的内存将一直存在,直到使用`delete` 运算符将其释放或程序结束为止。这种内存存储为动态方式。 ## 四、线程存储 C++11引入。 线程存储持续性。多核处理器中,多个CPU同时处理多个执行的任务,这让程序能够将计算放在可并行处理的不同线程中。如果变量是使用关键字 `thread_local` 声明的,则其变量的生命周期和其所属的线程一样长。