首页 > 编程语言 > 详细

C++内存分配方式

时间:2019-12-24 01:29:29      阅读:116      评论:0      收藏:0      [点我收藏+]

内存管理是C++最令人头痛的问题,也是C++最有争议的地方。C++高手从中获得了更好的性能,更大的自由,C++菜鸟获取的则是一遍一遍的检查代码。而这一切都源于C++内存管理的灵活性,其多样的内存分配方式就是其灵活性的最好例证之一。

一个程序要运行,就必须先将可执行的程序加载到计算机内存里,程序加载完毕后,会形成一个运行空间,并按照下图所示进行布局。

技术分享图片

  • 代码区:存放的是程序的执行代码;
  • 数据区:存放的是全局数据、常量、静态变量等;
  • 堆区:存放的是动态内存,供程序随机申请使用;
  • 栈区:存放的是程序中所用到的局部数据。

这些数据可以动态地反应程序中对函数的调用状态,通过其轨迹也可以研究其函数机制。其中,除了代码区不是我们能在代码中直接控制的,剩余三块都是我们编码过程中可以利用的。

在C++中,数据区又被分成自由存储区、全局/静态存储区和常量存储区,再加上堆区、栈区,也就是说内存被分成了5个区。这5种不同的分区各有所长,适用于不同的情况。

栈区

在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元将自动被释放。栈内存分配运算内置于处理器的指令集中,效率很高,但是所分配的内存容量有限。

堆区

堆就是那些由new分配的内存块,用delete来释放内存。如果程序员没有释放掉,那么在程序结束后,操作系统就会自动回收。

自由存储区

自由存储区是那些由malloc等分配的内存块,它和堆十分相似,不过它是用free来结束自己生命的。

全局/静态存储区

全局变量和静态变量被分配到同一块内存中,在以前的C语言中,全局变量又分为初始化的和未初始化的,在C++里面没有作此区分,它们共同占用同一块内存区。

常量存储区

比较特殊,里面存放的是常量,不允许修改。

堆与栈的区别

上述5种分区中,最常用的就是堆和栈了,最容易混淆的也是它们。所以搞清楚堆和栈的区别是很有必要的。它们的区别主要有以下几个方面

1. 管理方式

栈是由编译器自动管理的,无须手工控制;堆的释放工作由程序员控制,容易产生内存泄漏。

2. 空间大小

一般来说在32位系统下,堆内存可以达到4GB(2^32B = 4 * 2^30B = 4GB)的空间,从这个角度来看堆内存几乎是没有什么限制的。但是对于栈来讲,一般都是有一定空间大小的。例如,VS2017默认栈空间大小是1M。

3. 碎片问题

对堆来讲,频繁的new/delete会造成内存空间的不连续,从而产生大量的碎片,使程序效率降低。对于栈来讲,则不存在这个问题,因为栈是队列,其中的数据必须遵循先进后出的规则,相互之间紧密排列,绝不会留给其他数据可插入之空隙,所以永远都不可能有一个内存块从栈中间弹出。

4. 生长方向

对于堆来讲,其生长方向是向上的,也就是向着内存地址增加的方向增长;对于栈来讲,它的生长方向是向下的,是向着内存地址减小的方向增长的。

5. 分配方式

堆都是动态分配的,没有静态分配的堆。栈有两种分配方式:静态分配和动态分配。静态分配是编译器完成的,比如局部变量的分配。动态分配由alloca函数完成,但是栈的动态分配和堆是不同的,它的动态分配是由编译器进行释放的,无须我们手工实现。

6. 分配效率

栈是系统提供的数据结构,计算机会在底层对栈提供支持:它会分配专门的寄存器存放栈的地址,而且压栈出栈都会有专门的指令来执行,这就决定了栈的效率比较高。堆则是C/C++函数库提供的,它的机制很复杂,例如为了分配一块内存,库函数会按照一定的算法(具体的算法可以参考数据结构/操作系统)在堆内存中搜索可用的足够大小的空间,如果没有足够大小的空间(可能是由于内存碎片太多),则可能调用系统功能去增加程序数据段的内存空间,这样就有机会分到足够大小的内存了,然后返回。显然,堆的效率比栈要低得多。

总结

堆和栈相比,由于堆使用了大量new/delete,容易造成大量的内存碎片,而且它没有专门的系统支持,效率很低,另外它还可能引发用户态和核心态的切换,以及内存的申请,代价会变得很高。所以栈在程序中是应用最广泛的,就算是函数的调用也会利用栈去完成,函数调用过程中的参数、返回的地址、EBP和局部变量都是采用栈的方式存放的。所以,推荐大家尽量多用栈,而不是用堆。

虽然栈有如此多的好处,但是由于和堆相比它不是那么灵活,有时候会分配大量的内存空间,在遇到这种情况时还是用堆好一些。


个人主页:

www.codeapes.cn

C++内存分配方式

原文:https://www.cnblogs.com/codeapes666/p/12089164.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!