栈区与堆区

来源:互联网 发布:centos gcc 升级 编辑:程序博客网 时间:2024/04/30 15:09

内存内部的组织情况:

从上图可知,程序占用的内存被分了以下几部分.

1、栈区(stack)

由编译器自动分配释放 ,存放函数的参数值,局部变量的值等,内存的分配是连续的,类似于平时我们所说的栈,

如果还不清楚,那么就把它想成数组,它的内存分配是连续分配的,

即,所分配的内存是在一块连续的内存区域内.当我们声明变量时,那么编译器会自动接着当前栈区的结尾来分配内存.

2、堆区(heap)

一般由程序员分配释放, 若程序员不释放,程序结束时可能由操作系统回收.

类似于链表,在内存中的分布不是连续的,它们是不同区域的内存块通过指针链接起来的一旦某一节点从链中断开,我们要人为的把所断开的节点从内存中释放

3、全局区(静态区)(static)

全局变量和静态变量的存储是放在一块的,

初始化的全局变量和静态变量在一块区域,

未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。 程序结束后由系统释放

4、文字常量区

常量字符串就是放在这里的。 程序结束后由系统释放

5、程序代码区

存放函数体的二进制代码。

先看一个例子:

char c; //栈上分配
char *p = new char[3]; //堆上分配,将地址赋给了p;

  • 在 编译器遇到第一条指令时,计算其大小,然后去查找当前栈的空间是大于所需分配的空间大小,

         如果这时栈内空间大于所申请的空间,那么就为其分配内存空间,

注 意:在这里,内在空间的分配是连续的,是接着上次分配结束后进行分配的.如果栈内空间小于所申请的空间大小,那么这时系统将揭示栈溢出,并给出相应的异常 信息

  • 编译器遇到第二条指令时,由于p是在栈上分配的,所以在为p分配内在空间时和上面的方法一样,但当遇到new关 键字,那么编译器都知道,这是用户申请的动态内存空间,所以就会转到堆上去为其寻找空间分配.

注意:堆上的内存空间不是连续的,它是由相应的链表将其 空间区时的内在区块连接的,所以在接到分配内存空间的指定后,它不会马上为其分配相应的空间,而是先要计算所需空间,然后再到遍列整个堆(即遍列整个链的 节点),将第一次遇到的内存块分配给它,最后再把在堆上分配的字符数组的首地址赋给p.,这个时候,大家已经清楚了,p中现在存放的是在堆中申请的字符数组的首地址,也就是在堆中申请的数组的地址现在被赋给了在栈上申请的指针变量p.为了更加形象的说明问题,请看下图:

存取效率比较:

char s1[] = "aaaaaaaaaaaaaaa";
char
 *s2 = "bbbbbbbbbbbbbbbbb";

aaaaaaaaaaa是在运行时刻赋值的;

而bbbbbbbbbbb是在编译时就确定的;

但是,在以后的存取中,在栈上的数组比指针所指向的字符串(例如堆)快。

原文:http://www.cnblogs.com/zhangchenliang/archive/2012/04/26/2471435.html

c++中从栈实例化对象与从堆实例化对象(new  运算符)

//栈实例化:   类名 对象名 或类名 数组名;

说明:

TV   tv;定义了一个对象

TV tv[20];定义了一个对象数组。


//堆实例化:;

从栈类型的对象直接使用“.”访问成员,而堆中的对象要使用“->”指针访问成员

注意:在栈上所申请的内存空间,当我们出了变量所在的作用域后,系统会自动我们回收这些空间;

而在堆上申请的空间,当出了相应的作用域以后,我们需要显式 的调用delete来释放所申请的内存空间,

如果我们不及时得对这些空间进行释放,那么内存中的内存碎片就越来越多,从而我们的实际内存空间也就会变的越 来越少,即,孤立的内存块越来越多.在这里,我们知道,堆中的内存区域不是连续的,还是将有效的内存区域经过链表指针连接起来的,如果我们申请到了某一块 内存,那么这一块内存区将会从连续的(通过链表连接起来的)内存块上断开,如果我们在使用完后,不及时的对它进行释放,那么它就会孤立的开来,由于没有任何指针指向它,所以这个区域将成为内存碎片,所以在使用完动态分配的内存(通过NEW申请)后,一定要显式的对它进行DELETE删除.对于这一点,一定 要切记..


0 0
原创粉丝点击