当前位置: 主页 > 程序 >

堆?栈?堆栈?

时间:2017-01-25  作者:haden   点击:
【摘要】堆?栈?堆栈?傻傻分不清楚!

简单来说:

堆 = 堆(heap)
栈 = 栈(stack)
堆栈 = 栈(stack)

堆:顺序随意
栈:先进后出

 

好了,正文结束,大家可以散了!

 

 
 
 

预备知识——程序的内存分配

 

一个由 C/C++ 编译的程序占用的内存分为以下几个部分

1、栈区(stack):由编译器自动分配释放,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。  

2、堆区(heap):一般由程序员分配释放,若程序员不释放,程序结束时可能由OS回收。注意它与数据结构中的堆是两回事,分配方式倒是类似于链表。

3、全局区(静态区)(static):全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域,未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。程序结束后由系统释放。  

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

5、程序代码区—存放函数体的二进制代码。  

 

 
 
 

例子程序

 

//main.cpp
int a = 0;  //全局初始化区
char *p1;   //全局未初始化区
main()
{
    int b;      //栈
    char s[] = "abc";   //栈
    char *p1;           //栈
    char *p2;           //栈
    char *p3 = "123456";    //123456/0在常量区,p3在栈上
    static int c = 0;       //全局(静态)初始化区
    p1 = (char *)malloc(10);
    p2 = (char *)malloc(20);//分配来的10和20字节区域就在堆区
    strcpy(p1,"123456");    //123456/0放在常量区,编译器可能会将它与p3所指向的“123456”优化成一个地方
}                

 

 
 
 

堆和栈

1、申请方式:

stack:系统自动分配。如:int b;

heap:需要程序员自己申请并指明大小。如:p2 = new char[10];

 

2、申请后相应过程

stack:只要栈的剩余空间大于申请空间,系统将为程序提供内存,否则将报异常提示栈溢出。

heap:操作系统由一个记录空闲内存地址的链表,系统收到申请会遍历链表,寻找第一个空间大于申请空间的堆结点,然后将结点从链表中删除并分配给程序。

 

3、申请大小限制

stack:在Windows下,栈是向低地址扩展的数据结构,是一块连续的内存区域。大小编译时就确定。

heap:向高地址扩展的数据结构,是不连续的内存区域。堆的大小受限于计算机系统中的有效虚拟内存。堆获得空间更灵活,也比较大。

 

4、申请效率

栈由系统自动分配,速度比较快,但是程序员无法控制。

堆是由 new 分配的内存,一般速度比较慢,易产生内存碎片。

 

5、存取效率

//main.cpp
main()
{
    //aaaaaaaaa是在运行时赋值的,栈
    char s1[] = "aaaaaaaaa";
    //bbbbbbbbb是在编译时就确定的,堆
    char *s2 = "bbbbbbbbb";
    char a = 1;    
    
    //以后的存取中,栈上的数组比指针所指向的字符串快
    a = s1[1];      //快
    a = s2[1];      //慢
    return;
}                

通过查看汇编代码

;a = s1[1]
MOV cl,byte ptr [edp-0FH]
MOV byte ptr [ebp-4],cl
;a = s2[1]
MOV edx,dword ptr [ebp-14H]
MOV al,byte ptr [edx+1]
MOV byte ptr [edx -4],al

 

 
 
 
总结

 

使用栈就像我们去饭馆吃饭,只管点菜(发出申请)、付钱和吃(使用),吃饱了就走,不必理会切菜、洗菜等准备工作和洗碗、刷锅等扫尾工作。好处是快捷,但是自由度小。

使用堆就是自己动手做喜欢的菜肴,比较麻烦,但是符合自己的胃口,而且自由度较大。


顶一下
(4)
100%
踩一下
(0)
0%
发表评论
请自觉遵守互联网相关的政策法规,严禁发布色情、暴力、反动的言论。
评价:
验证码: 点击我更换图片

推荐内容