- 栈(
stack
): 由编译器自动分配, 存放函数的参数值, 局部变量的值等. 其操作方式类似于数据结构中的栈. - 堆(
heap
): 一般由程序员分配释放, 若程序员不释放, 程序结束时可能由OS
回收. 这里OS
是指: 操作系统(Operating System)
区别和联系:
- 申请方式
- 堆: 由程序员自己申请并指明大小, 在
c
语言中的malloc
函数. eg:p1 = (char *)malloc(10)
; - 栈: 由系统自动分配, eg: 声明在函数中的一个局部变量
int b
; 系统自动在栈中为b
开辟空间;
- 堆: 由程序员自己申请并指明大小, 在
- 申请后系统的响应
- 堆: 首先应该知道操作系统有一个记录空闲内存地址的链表, 当系统收到程序的申请时, 会遍历该链表, 寻找第一个空间大于所申请空间的堆结点, 然后将该结点从空闲结点链表中删除, 并将该结点的空间分配给程序, 对于大多数系统, 会在这块内存空间中的首地址处记录本次分配的大小, 这样代码中的
delete
语句才能正确的释放本内存空间. 另外, 由于找到的堆节点的大小不一定正好等于申请的大小, 系统会自动的将多余的那部分重新放入空闲链表中. - 栈: 只要栈的剩余空间大于所申请空间, 系统将为程序员提供内容, 否则将异常提示栈溢出;
- 堆: 首先应该知道操作系统有一个记录空闲内存地址的链表, 当系统收到程序的申请时, 会遍历该链表, 寻找第一个空间大于所申请空间的堆结点, 然后将该结点从空闲结点链表中删除, 并将该结点的空间分配给程序, 对于大多数系统, 会在这块内存空间中的首地址处记录本次分配的大小, 这样代码中的
- 申请大小的限制
- 堆: 向高地址扩展的数据结构, 是不连续的内存区域. 这是由于系统是用链表来存储空闲内存地址的, 自然是不连续的, 而链表的遍历方向是由低地址向高地址. 堆的大小受限于计算机系统中有效的虚拟内存. 由此可见, 堆获得的空间比较灵活, 也比较大.
- 栈: 在
Windows
下, 栈是向低地址扩展的数据结构, 是一块联系的内存区域. 这句话的意思是栈顶的地址和栈的最大容量是系统预先规定好的, 在Windows
下, 栈的大小是2M(也有人说1M, 总之是一个编译时就确定的常数), 如果申请的空间超过栈的剩余空间, 将提示overflow
. 因此, 能从栈获得的空间较小.
- 申请效率
- 堆: 由
new
分配的内存, 一般速度比较慢, 而且容易产生内存碎片, 不过用起来最方便; - 栈: 系统自动分配, 速度较快. 但是程序员无法控制;
- 堆: 由
通俗易懂的方式来解释堆与栈之间的区别
- 区别一(who)
- 堆: 可以把堆理解为 土堆 , 堆是由程序员负责分配和释放的. 而程序员又被称为码农, 即为 农名(这里没有任何鄙视农名的意思, 我的爸妈也是农名, 这里只是作为一种便于理解的比喻), 农名 就是种地的(操作 土堆).
- 栈: 可以把栈理解为 书 , 读书人有知识、文化, 什么都是自动的、高科技, 所以栈是不用 农名 关心的, 由操作系统自己去申请和释放的.
- 区别二(where)
- 堆: 可以想象 土堆 被操作时 肯定没有那么智能化, 所以分配的时候会去查找合适的空间, 能找到放下 土堆 的容量的内存块的时候就分配给你.
- 栈: 书 是很智能化的, 所以操作系统会直接给你了.
- 区别三(how)
- 堆: 土堆 只能够从地上往上堆, 不可能相反, 那样的土堆除非有502(胶水). 所以是从下往上分配地址的.
- 栈: 书 我们可以想象成一个未来的图书馆, 图书馆把 书 都放在天花板上, 从上往下放, 而且不会掉下来. 所以栈的分配是自顶向下的, 而且坑定有空间限制. 所以如果栈上空间不足了就
overflow
了.
- 区别四(result)
- 堆: 土堆 农业相关, 所以什么都比较慢, 所以分配就比较慢了, 而且到处都是 小土堆 , 这就是碎片.
- 栈: 书 高科技的, 当然分配就很快, 至少比堆快, 而且不会有碎片, 人家是高科技的产物.