栈和堆、栈区和堆区二者区别

一、二者区别

    1、首先,栈和堆是数据结构里面的叫法,栈:先进后出,堆:优先队列可采用二叉树实现;  

     2、内存模型里面的栈区和堆区和数据结构没有关系,底层也不是讲用了数据结构里面的堆栈的存储方式。但是类似,栈区(stack) 由编译器自动分配释放 ,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。堆区(heap)一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收 。注意它与数据结构中的堆是两回事,分配方式倒是类似于链表。

二、内存模型中的堆区和栈区

      这是一个围绕:What and where are the stack and heap?的提问,网址:https://stackoverflow.com/questions/79923/what-and-where-are-the-stack-and-heap

      我结合他的回答,总结补充一下。

1、栈。
       因为栈主要是为一个线程配备(栈是线程独享的)为这个线程的函数调用服务的。用于存放返回地址,参数,临时变量而用,记录多层调用,是一个有明确的“后入先出”规则的内存 buffer。而且是供程序员“隐式”的使用,分配和回收都是“自动”的,程序员对栈内存的使用缺少自由和可控性, 栈这部分内存由专用的寄存器和指令来负责维护。其特点是栈的“复用率”很高,是连续的,且有 IN - OUT 次序的(对 ESP 的维护非常严格严谨,这个工作是编译器来负责,通常也不需要程序员去干预。计算机会在底层对栈提供支持:分配专门的寄存器存放栈的地址,压栈出栈都有专门的指令执行,这就决定了栈的效率比较高。
      栈上对象的特点是尺寸小而且生命周期很短,潜规则是不要创建尺寸极大的临时对象,调用深度也不希望过深。所以如果栈太大,则对内存使用的性价比会降低(栈的顶部方向的那部分属于栈所有但位于栈外的那部分内存是几乎不会被使用到的,距离栈顶越远的栈外内存的被使用的概率越低,距离栈底越近的内存则使用率越高,热点集中在靠近栈底的部分,而远端方向则是空白的,就好像地铁车厢的高度,不会因为一个姚明这样的存在就把它设计的很高,那样就属于浪费),而且也会减少可以同时创建的进程的数量。
      栈只能进行push和pop两种操作,无论是排序,寻址,还是修改,删除,插入都很难,时间代价太高了。所以其实不是不能将栈变得很大,而是因为一旦变得很大,它在这个场景下就不是一个合理的数据结构了,应该选择其他的数据结构来解决。
2、堆。
       而堆内存的使用特点是不连续和无序的,分配和释放成本较高堆则是C/C++函数库提供的,它的机制是很复杂的,例如为了分配一块内存,库函数会按照一定的算法(具体的算法可以参考数据结构/操作系统)在堆内存中搜索可用的足够大小的空间,如果没有足够大小的空间(可能是由于内存碎片太多),就有可能调用系统功能去增加程序数据段的内存空间,这样就有机会分到足够大小的内存,然后进行返回。 显然,堆的效率比栈要低得多。 ,
3、因此,栈和堆的设计体现了“分工”原则。栈的主要作用的为函数调用服务,并承担了生命周期很短和(编译器)“自动”维护,尺寸很小的临时对象的存储责任。堆则负责存储生命周期由程序员自主维护,以及尺寸极大的(例如明显超过栈的尺寸)对象/数据。
4、栈和堆的大小
  栈的大小在进程分配时是确定的,具体大小看编译器,操作系统。由于栈先进后出的特性存取非常快,实际上也不是什么分配,只是从栈顶向上用就行,就好像工厂中的传送带(conveyorbelt)一样,StackPointer会自动指引你到放东西的位置,你所要做的只是把东西放下来就行.退出函数的时候,修改栈指针就可以把栈中的内容销毁.这样的模式速度最快。所需大小一般小于10M!太大没有意义!
  堆是动态分配的,堆的数据结构相对较慢!因为会手动进行分配,会大一些。是自底向上分配,从低地址往高地址分配,大小不固定。栈相反。
5、哪个快 ?
  至于堆和栈哪个更快,从两方面来考虑:
      (1)分配和释放,堆在分配和释放时都要调用函数(MALLOC,FREE),比如分配时会到堆空间去寻找足够大小的空间(因为多次分配释放后会造成空洞),这些都会花费一定的时间,具体可以看看MALLOC和FREE的源代码,他们做了很多额外的工作,而栈却不需要这些。
     (2)访问时间,访问堆的一个具体单元,需要两次访问内存,第一次得取得指针,第二次才是真正得数据,而栈只需访问一次。另外,堆的内容被操作系统交换到外存的概率比栈大,栈一般是不会被交换出去的。 

猜你喜欢

转载自www.cnblogs.com/huangfuyuan/p/9150362.html