您的位置 首页 基础

仓库入门——堆和栈差异

在计算机领域,堆栈是一个不容忽视的概念,我们编写的C语言程序基本上都要用到。但对于很多的初学着来说,堆栈是一个很模糊的概念。堆栈:

在计算机范畴,是一个不容忽视的概念,咱们编写的C言语程序基本上都要用到。但关于许多的初学着来说,仓库是一个很含糊的概念。仓库:一种数据结构、一个在程序运转时用于寄存的当地,这可能是许多初学者的知道,因为我从前便是这么想的和汇编言语中的仓库一词相提并论。我身边的一些编程的朋友以及在网上看帖遇到的朋友中有很多也说不清仓库,所以我想有必要给咱们共享一下我对仓库的观点,有说的不对的当地请朋友们不吝赐教,这关于咱们学习会有很大协助。
首要在数据结构上要知道仓库,尽管咱们这么称号它,但实际上仓库是两种数据结构:堆和栈。
堆和栈都是一种数据项按序摆放的数据结构。
咱们先从咱们比较了解的栈说起吧,它是一种具有后进先出性质的数据结构,也便是说后寄存的先取,先寄存的后取。这就好像咱们要取出放在箱子里边底下的东西(放入的比较早的物体),咱们首要要移开压在它上面的物体(放入的比较晚的物体)。而堆就不同了,堆是一种通过排序的树形数据结构,每个结点都有一个值。一般咱们所说的堆的数据结构,是指二叉堆。堆的特点是根结点的值最小(或最大),且根结点的两个子树也是一个堆。因为堆的这个特性,常用来完成优先行列,堆的存取是随意,这就好像咱们在图书馆的书架上取书,尽管书的摆放是有次序的,可是咱们想取恣意一本时不用像栈相同,先取出前面一切的书,书架这种机制不同于箱子,咱们能够直接取出咱们想要的书。
可是我要说的要点并不在这,我要说的堆和栈并不是数据结构的堆和栈,之所以要说数据结构的堆和栈是为了和后边我要说的堆区和栈戋戋别开来,请咱们必定要留意。
下面就说说C言语程序内存分配中的堆和栈,这儿有必要把内存分配也提一下,咱们不要嫌我烦琐,一般情况下程序寄存在Rom或Flash中,运转时需求拷到内存中履行,内存会别离存储不同的信息,如下图所示:

内存中的栈区处于相对较高的地址以地址的增加方向为上的话,栈地址是向下增加的,栈中分配局部变量空间,堆区是向上增加的用于分配程序员请求的内存空间。别的还有静态区是分配静态变量,大局变量空间的;只读区是分配常量和程序代码空间的;以及其他一些分区。

来看一个网上很盛行的经典比方:
main.cpp
  int a = 0; 大局初始化区
  char *p1; 大局未初始化区
  main()
  {
  int b; 栈
  char s[] = “abc”; 栈
  char *p2; 栈
  char *p3 = “123456”; 123456在常量区,p3在栈上。
  static int c =0; 大局(静态)初始化区
  p1 = (char *)malloc(10);
  p2 = (char *)malloc(20);
  }
  
不知道你是否有点理解了,堆和栈的第一个差异便是请求方法不同:栈(英文名称是stack)是体系主动分配空间的,例如咱们界说一个 char a;体系会主动在栈上为其拓荒空间。而堆(英文名称是heap)则是程序员根据需求自己请求的空间,例如malloc(10);拓荒十个字节的空间。因为栈上的空间是主动分配主动收回的,所以栈上的数据的生计周期只是在函数的运转过程中,运转后就开释掉,不能够再拜访。而堆上的数据只需程序员不开释空间,就一向能够拜访到,不过缺陷是一旦忘掉开释会形成内存走漏。还有其他的一些差异我以为网上的朋友总结的不错这儿转述一下:

1.请求后体系的呼应
  栈:只需栈的剩下空间大于所请求空间,体系将为程序供给内存,否则将报反常提示栈溢出。
  堆:首要应该知道操作体系有一个记载闲暇内存地址的链表,当体系收到程序的请求时,会遍历该链表,寻觅第一个空间大于所请求空间的堆结点,然后将该结点从闲暇结点链表中删去,并将该结点的空间分配给程序,别的,关于大多数体系,会在这块内存空间中的首地址处记载本次分配的巨细,这样,代码中的 delete句子才干正确的开释本内存空间。别的,因为找到的堆结点的巨细不用定正好等于请求的巨细,体系会主动的将剩下的那部分从头放入闲暇链表中。
也便是说堆会在请求后还要做一些后续的作业这就会引出请求功率的问题

2.请求功率的比较
  栈由体系主动分配,速度较快。但程序员是无法控制的。
  堆是由new分配的内存,一般速度比较慢,并且简单发生内存碎片,不过用起来最便利.

3.请求巨细的约束
  栈:在Windows下,栈是向低地址扩展的数据结构,是一块接连的内存的区域。这句话的意思是栈顶的地址和栈的最大容量是体系预先规定好的,在 WINDOWS下,栈的巨细是2M(也有的说是1M,总归是一个编译时就确认的常数),假如请求的空间超越栈的剩下空间时,将提示overflow。因而,能从栈取得的空间较小。
  堆:堆是向高地址扩展的数据结构,是不接连的内存区域。这是因为体系是用链表来存储的闲暇内存地址的,自然是不接连的,而链表的遍历方向是由低地址向高地址。堆的巨细受限于计算机体系中有用的虚拟内存。由此可见,堆取得的空间比较灵敏,也比较大。
  
4.堆和栈中的存储内容
  栈:在函数调用时,第一个进栈的是主函数中函数调用后的下一条指令(函数调用句子的下一条可履行句子)的地址,然后是函数的各个参数,在大多数的C编译器中,参数是由右往左入栈的,然后是函数中的局部变量。留意静态变量是不入栈的。

回来地址

  函数的参数

  局部变量

  当本次函数调用完毕后,局部变量先出栈,然后是参数,最终栈顶指针指向最开端存的地址,也便是主函数中的下一条指令,程序由该点持续运转。

  堆:一般是在堆的头部用一个字节寄存堆的巨细。堆中的具体内容有程序员组织。

5.存取功率的比较 
  char s1[] = “aaaaaaaaaaaaaaa”;
  char *s2 = “bbbbbbbbbbbbbbbbb”;
  aaaaaaaaaaa是在运转时间赋值的;
  而bbbbbbbbbbb是在编译时就确认的;
  可是,在今后的存取中,在栈上的数组比指针所指向的字符串(例如堆)快。
  比方:
  #i nclude
  void main()
  {
  char a = 1;
  char c[] = “1234567890”;
  char *p =”1234567890″;
  a = c[1];
  a = p[1];
  return;
  }
  对应的汇编代码
  10: a = c[1];
  00401067 8A 4D F1 mov cl,byte ptr [ebp-0Fh]
  0040106A 88 4D FC mov byte ptr [ebp-4],cl
  11: a = p[1];
  0040106D 8B 55 EC mov edx,dword ptr [ebp-14h]
  00401070 8A 42 01 mov al,byte ptr [edx+1]
  00401073 88 45 FC mov byte ptr [ebp-4],al

堆和栈的差异能够引证一位长辈的比方来看出:
  
运用栈就象咱们去饭馆里吃饭,只管点菜(宣布请求)、付钱、和吃(运用),吃饱了就走,不用理睬切菜、洗菜等准备作业和洗碗、刷锅等扫尾作业,他的优点是方便,可是自由度小。
  
运用堆就象是自己动手做喜欢吃的菜肴,比较费事,可是比较契合自己的口味,并且自由度大。比方很形象,说的很通俗易懂,不知道你是否有点收成。

声明:本文内容来自网络转载或用户投稿,文章版权归原作者和原出处所有。文中观点,不代表本站立场。若有侵权请联系本站删除(kf@86ic.com)https://www.86ic.net/zhishi/jichu/256861.html

为您推荐

联系我们

联系我们

在线咨询: QQ交谈

邮箱: kf@86ic.com

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

返回顶部