程序开始运行前,系统为程序在内存中开辟空间,这片空间中有两个部分,分别是堆和栈
NOTE
因为程序会频繁访问栈空间,栈空间的数据往往活跃在 CPU 缓存中,但是栈数据仍然是存储在内存中
堆和栈的原理和运行方式十分相似,两者都是存储在内存空间,为程序运行过程中的输入和输出数据提供空间,在用户请求空间时,两者都会返回一个符合用户要求的内存块。两者的不同之处在于,如何给用户分配内存
在栈中分配空间时,只需移动栈顶指针开辟指定大小空间即可,所以栈空间的对象在物理地址上是连续的(调试的时候观察内存空间的变化),作用域结束后对象生存周期也随之结束,需要回收栈中空间,将栈中对象弹出后,栈顶指针自然回到作用域之前,因此栈空间的分配回收效率高
在堆中分配空间时,需要调用 new 关键字,而 new 关键字调用了 malloc 函数,进而调用底层操作系统的特定函数。在程序开始时会维护一个空闲空间表,跟踪空闲内存块,当使用 malloc 分配动态堆内存时,会从空闲空间表中寻找一块可以容纳请求大小的内存块并返回对应的指针,系统也会更新空闲空间表,记录分配的相关信息,当请求的空间超过了空闲内存表中的大小,程序则需要向系统请求更大的内存空间,影响程序运行效率,并且堆分配的地址是分散的。
栈分配就是一条 CPU 指令(汇编中仅需一条指令),而堆分配就是在一堆里面分配(寻找是否有空位,分配后记录分配的相关信息),因为栈中数据的物理地址连续,使得这些数据可以放到 CPU 的缓存中进行加速,而堆会频繁出现 MISS(CPU 想访问的数据不在缓存中)
TIP
在内存分配上尽可能使用栈分配,除非需要变量的生命周期超过了作用域或者分配巨大的内存空间,否则使用堆会降低运行效率