没有合适的资源?快使用搜索试试~ 我知道了~
主要介绍堆和栈的概念、区别、优缺点等,以及在实际的项目开发中使用堆还是栈
资源推荐
资源详情
资源评论
栈比堆快的原因:
栈是机器系统提供的数据结构,计算机会在底层对栈提供支持:分配专门的寄存器存放栈的地址,压栈出栈都有专门的指令执行,这就决定了栈的效率比较高。
堆则是C/C++函数库提供的,它的机制很复杂,例如:为了分配一块内才能,库函数会按照一定的算法,在堆内存中搜索可用的足够大小的空间,如果没有足够大小的空间,就有可能调用系统功能区增加程序数据段内存空间,这样就有机会分配到足够大小的内存,然后返回。堆得效率比栈低得多。
C/C++中,所有的方法调用都是通过栈来进行的。
一、堆和栈
1.内存分配方面:
堆:一般由程序员分配释放,若程序员不释放,程序结束时可能由OS回收。分配方式类似于链表,关键字:new、malloc、delete、free等。
栈:由编译器自动分配释放,存放函数的参数值、局部变量的值等,操作方式类似于数据结构中的栈。
2.申请方式方面:
堆:需要程序员自己申请,并声明大小。在C中malloc函数,c++中用new运算符
栈:由系统自动分配。例如:声明在函数中一个局部变量int a,系统自动在栈中为a开辟空间。
3.系统响应方面:
堆:OS有一个记录空闲内存地址的链表,当OS收到程序员的申请时,会遍历链表,寻找一个空间大于所申请空间的对结点,然后将该结点从空闲结点链表中删除,并将该结点的空间分配给程序,另外,对于大多数OS,会在这块内存空间中的首地址处记录本次分配的大小,这样代码中的delete语句才能正确的释放本内存空间。由于找到的堆结点的大小不一定正好等于申请的大小,系统会自动的将多余的那部分重新放入空闲链表中。
栈:只要栈的剩余空间大于所申请的空间,OS将为程序提供内存,否则将会报异常提示栈溢出。
4.大小限制方面:
堆:是向高地址扩展的数据结构,是不连续的内存空间。由于系统是用链表来存储的空闲内存地址,自然是不连续的,而链表的遍历方向是由低地址向高地址。堆的大小受限于计算机系统中有效的虚拟内存。由此可见,堆获得的空间比较灵活,也比较大。
栈:在Windows下,栈是向低地址扩展的数据结构,是一块连续的内存区域。也就是说栈顶的地址和栈的最大容量是系统预先规定好的,在Windows下,栈的大小固定的(是一个编译时就确定的常数),如果申请的空间超过栈的剩余空间时,将提示overfolw,因此,能从栈获得的空间较小。
5.效率方面:
栈是机器系统提供的数据结构,计算机会在底层对栈提供支持:分配专门的寄存器存放栈的地址,压栈出栈都有专门的指令执行,这就决定了栈的效率比较高。
堆则是C/C++函数库提供的,它的机制很复杂,例如:为了分配一块内才能,库函数会按照一定的算法,在堆内存中搜索可用的足够大小的空间,如果没有足够大小的空间,就有可能调用系统功能区增加程序数据段内存空间,这样就有机会分配到足够大小的内存,然后返回。堆得效率比栈低得多。
C/C++中,所有的方法调用都是通过栈来进行的。
一、堆和栈
1.内存分配方面:
堆:一般由程序员分配释放,若程序员不释放,程序结束时可能由OS回收。分配方式类似于链表,关键字:new、malloc、delete、free等。
栈:由编译器自动分配释放,存放函数的参数值、局部变量的值等,操作方式类似于数据结构中的栈。
2.申请方式方面:
堆:需要程序员自己申请,并声明大小。在C中malloc函数,c++中用new运算符
栈:由系统自动分配。例如:声明在函数中一个局部变量int a,系统自动在栈中为a开辟空间。
3.系统响应方面:
堆:OS有一个记录空闲内存地址的链表,当OS收到程序员的申请时,会遍历链表,寻找一个空间大于所申请空间的对结点,然后将该结点从空闲结点链表中删除,并将该结点的空间分配给程序,另外,对于大多数OS,会在这块内存空间中的首地址处记录本次分配的大小,这样代码中的delete语句才能正确的释放本内存空间。由于找到的堆结点的大小不一定正好等于申请的大小,系统会自动的将多余的那部分重新放入空闲链表中。
栈:只要栈的剩余空间大于所申请的空间,OS将为程序提供内存,否则将会报异常提示栈溢出。
4.大小限制方面:
堆:是向高地址扩展的数据结构,是不连续的内存空间。由于系统是用链表来存储的空闲内存地址,自然是不连续的,而链表的遍历方向是由低地址向高地址。堆的大小受限于计算机系统中有效的虚拟内存。由此可见,堆获得的空间比较灵活,也比较大。
栈:在Windows下,栈是向低地址扩展的数据结构,是一块连续的内存区域。也就是说栈顶的地址和栈的最大容量是系统预先规定好的,在Windows下,栈的大小固定的(是一个编译时就确定的常数),如果申请的空间超过栈的剩余空间时,将提示overfolw,因此,能从栈获得的空间较小。
5.效率方面:
堆:是由new分配的内存,一般速度比较慢,易产生内粗碎片,但用起来很方便。在Windows最好的方式是用VirtualAlloc分配内存,它不在堆和栈中,是直接在进程的地址空间中保留一块内存,用起来最不方便,但速度快,很灵活。
栈:由系统自动分配,速度较快,但程序员无法控制。
6.存放内容方面;
堆:一般是在堆得头部用一个字节存放堆得大小。堆中的具体内容由程序员负责安排。
栈:在函数调用时,第一个进栈的是主函数中的下一条指令(函数调用语句的下一条可执行语句)的地址,然后是函数的各个参数,在大多数C编译器中,参数是由右往左入栈,然后是函数中的局部变量。注意:静态变量是不入栈的。当本次调用结束后,局部变量先出栈,然后是参数,最后是栈顶指针指向最开始存的地址,也就是主函数中的下一条指令,程序由该点继续运行。
7.存取效率方面:
堆:char *s = "adfg"; 存放在堆中的指针数据在编译时确定的。
栈:char a[] = "asdg"; 存放在栈中的数组在运行时赋值的,用数组比用指针速度要快一些,因为指针在底层汇编中需要用edx寄存器中转一下,而数组在栈上直接读取。
小结
1、静态变量不入栈。
2、栈由编译器自动分配和释放。栈中存放局部变量和参数,函数调用结束后,局部变量先出栈,然后是参数。
3、数组比用指针速度要快一些,因为指针在底层汇编中需要用edx寄存器中转一下,而数组在栈上直接读取。
4、堆是由程序员通过new、malloc、free、delete等指令进行分配和释放。如果程序员没有进行释放,程序结束时可能有OS回收。
5、堆是由new分配的内存,速度较慢;栈是由系统自动分配,速度较快。
6、比如存放在栈里面的数组,是在运行时赋值。而存在堆里面的指针数据,是在编译时就确定的。
二、在C中分为几个存储区
1.堆:一般由程序员分配释放,若程序员不释放,程序结束时可能由OS回收;
2.栈:由编译器自动分配释放;
3.全局区(静态区):全局变量和静态变量的存储放在一块的,初始化的全局变量和静态变量在一块区域,未初始化的全局变量和未初始化的静态变量在相邻的另一块区域,程序结束时释放;
4.有一个专门存放常量的地方,程序结束时释放。
在函数体中定义的变量通常是在栈上,用malloc, calloc, realloc等分配内存的函数分配得到的就是在堆上。在所有函数体外定义的是全局量,加了static修饰符后不管在哪里都存放在全局区(静态区),在所有函数体外定义的static变量表示在该文件中有效,不能extern到别的文件用,在函数体内定义的static表示只在该函数体内有效。另外,函数中的"adgfdf"这样的字符串存放在常量区。
例如:int a = 0;//全局初始化区
栈:由系统自动分配,速度较快,但程序员无法控制。
6.存放内容方面;
堆:一般是在堆得头部用一个字节存放堆得大小。堆中的具体内容由程序员负责安排。
栈:在函数调用时,第一个进栈的是主函数中的下一条指令(函数调用语句的下一条可执行语句)的地址,然后是函数的各个参数,在大多数C编译器中,参数是由右往左入栈,然后是函数中的局部变量。注意:静态变量是不入栈的。当本次调用结束后,局部变量先出栈,然后是参数,最后是栈顶指针指向最开始存的地址,也就是主函数中的下一条指令,程序由该点继续运行。
7.存取效率方面:
堆:char *s = "adfg"; 存放在堆中的指针数据在编译时确定的。
栈:char a[] = "asdg"; 存放在栈中的数组在运行时赋值的,用数组比用指针速度要快一些,因为指针在底层汇编中需要用edx寄存器中转一下,而数组在栈上直接读取。
小结
1、静态变量不入栈。
2、栈由编译器自动分配和释放。栈中存放局部变量和参数,函数调用结束后,局部变量先出栈,然后是参数。
3、数组比用指针速度要快一些,因为指针在底层汇编中需要用edx寄存器中转一下,而数组在栈上直接读取。
4、堆是由程序员通过new、malloc、free、delete等指令进行分配和释放。如果程序员没有进行释放,程序结束时可能有OS回收。
5、堆是由new分配的内存,速度较慢;栈是由系统自动分配,速度较快。
6、比如存放在栈里面的数组,是在运行时赋值。而存在堆里面的指针数据,是在编译时就确定的。
二、在C中分为几个存储区
1.堆:一般由程序员分配释放,若程序员不释放,程序结束时可能由OS回收;
2.栈:由编译器自动分配释放;
3.全局区(静态区):全局变量和静态变量的存储放在一块的,初始化的全局变量和静态变量在一块区域,未初始化的全局变量和未初始化的静态变量在相邻的另一块区域,程序结束时释放;
4.有一个专门存放常量的地方,程序结束时释放。
在函数体中定义的变量通常是在栈上,用malloc, calloc, realloc等分配内存的函数分配得到的就是在堆上。在所有函数体外定义的是全局量,加了static修饰符后不管在哪里都存放在全局区(静态区),在所有函数体外定义的static变量表示在该文件中有效,不能extern到别的文件用,在函数体内定义的static表示只在该函数体内有效。另外,函数中的"adgfdf"这样的字符串存放在常量区。
例如:int a = 0;//全局初始化区
剩余6页未读,继续阅读
资源评论
u010439656
- 粉丝: 0
- 资源: 2
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
最新资源
- KIMI大模型浏览器插件
- b61fa64a08a02de0e0d49d53bb84c444.amr
- 5ffd9193f6aec31bbf16030a46680dc7.avi
- DA14531-蓝牙传感器连接传输数据固件
- logisim实验MIPS运算器(ALU)设计(内含4位先行进位74182、四位快速加法器、32位快速加法器)-Educoder_logisim里面连线,实现4位先行进位74182和4位快速加法器-C
- 高等数学第一章第二节数列的极限
- Python 版冒泡排序算法源代码
- 基于YOLOv8的教室人脸识别 附源码 预训练模型
- 基于JAVA实现的用于全局监控网络请求错误并记录日志的library
- tensorflow-gpu-2.7.2-cp38-cp38-manylinux2010-x86-64.whl
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功