C++中内存的分配方式和分配区域.

堆、栈、静态存储区.

堆(heap):由程序员分配,new和delete。它们的释放编译器不管,由应用程序控制,一般一个new就要对应一个delete。如果程序员没有释放掉,那么在程序结束后,操作系统会自动回收。堆可以动态地扩展和收缩

栈(stack):就是那些由编译器在需要的时候分配,在不需要的时候自动清除的变量的存储区域。里面的变量通常是局部变量、函数参数等。在一个进程中,位于用户虚拟地址空间顶部的是栈,编译器用它来实现函数调用。

全局/静态存储区:内存在程序编译时就已分配好,这块内存在程序的整个运行期间都存在。程序结束后由系统释放。例如:全局变量,static变量。

 

程序例子://当然并不是我写的.

 

堆栈知识:
首先看下面一段代码:

我们可以看到,有一个指针p,对它分配了5个int型空间.
看到new我们可以知道,分配的是堆上的空间.
p是函数f()的局部变量,所以在栈上.
故这句话可以理解为:在栈内存中存放了一个指向(5个int型空间的堆内存)的指针 p.
当我们要释放这块内存的时候:就使用 delelte []p;(注意删除的是数组不是数.)

 

那么,堆和栈有什么不同呢:

  1. 管理方式不同
  2. 空间大小不同
  3. 产生碎片不同
  4. 生长方向不同
  5. 分配方式不同
  6. 分配效率不同

1.管理方式不同:

对于栈来讲,是编译器自动管理,无需手动控制.
对于堆来说,释放工作由程序员控制。

2.空间大小不同:

栈的大小:在WINDOWS下,栈的大小是2M(也有的说是1M,总之是一个编译时就确定的常数),如果申请的空间超过栈的剩余空间时,将提示overflow。因此,能从栈获得的空间较小。
堆的大小:堆的大小受限于计算机系统中有效的虚拟内存。由此可见,堆获得的空间比较灵活,也比较大。

3.产生碎片不同:

对于堆来讲,频繁的 new/delete 势必会造成内存空间的不连续,从而造成大量的碎片,使程序效率降低。对于栈来讲,则不会存在这个问题,因为栈是先进后出的队列,他们是如此的一一对应,以至于永远都不可能有一个内存块从栈中间弹出,在他弹出之前,在他上面的后进的栈内容已经被弹出了。

4.生长方向不同:

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

5.分配方式不同:

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

6.分配效率不同:

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

 

一般所说的堆栈(stack)往往是指栈,先进后出,它是一块内存区。用以存放程序的局部变量,临时变量,函数的参数,返回地址等。在这块区域中的变量的分配和释放由系统自动进行。不需要用户的参与。
而在堆(heap,先进先出)上的空间则是由用户进行分配,并由用户负责释放

【C++】内存分配方式
Tagged on:
0 0 投票数
Article Rating
订阅评论
提醒

0 评论
内联反馈
查看所有评论