c++ 内存分配

C++内存分配方式详解——堆、栈、自由存储区、全局/静态存储区和常量存储区

c++内存分配

c/c++中static关键字详解

c++ static

c++primer 220

 ---------------------------------------------------------------------------------

---------------------------------------------------------------------------------

在C++中,内存分成5个区

  1. 栈区(stack) 由编译器自动分配释放 ,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。
  2. 堆区(heap) 就是那些由 new 分配的内存块,一般一个 new 就要对应一个 delete一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收 。注意它与数据结构中的堆是两回事,分配方式倒是类似于链。堆可以动态地扩展和收缩。
  3. 自由存储区 就是那些由 malloc 等分配的内存块,他和堆是十分相似的,不过它是用 free 来结束自己的生命的。
  4. 全局区(静态区)(static)全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域data段, 未初始化的全局变量和未初始化的静态变量在相邻的另一块区域bss段。程序结束后有系统释放
  5. 常量存储区 存放的是常量,不允许修改。常量字符串就是放在这里的。常量字符串不能修改, 否则程序会在运行期崩溃(当然,你要通过非正当手段也可以修改,而且方法很多).程序结束后由系统释放

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

申请后系统的响应 

  • 栈:只要栈的剩余空间大于所申请空间,系统将为程序提供内存,否则将报异常提示栈溢出。
  • 堆:操作系统有一个记录空闲内存地址的链表,当系统收到程序的申请时, 会遍历该链表,寻找第一个空间大于所申请空间的堆结点,然后将该结点从空闲结点链表中删除,并将该结点的空间分配给程序。另外,对于大多数系统,会在这块内存空间中的首地址处记录本次分配的大小,这样,代码中的delete语句才能正确的释放本内存空间。另外,由于找到的堆结点的大小不一定正好等于申请的大小,系统会自动的将多余的那部分重新放入空闲链表中。

申请大小的限制

  • 栈:在Windows下,栈是向低地址扩展,从上到下生长的扩展的数据结构,是一块连续的内存的区域。这句话的意思是栈顶的地址和栈的最大容量是系统预先规定好的,在WINDOWS下,栈的大小是2M(也有的说是1M,总之是一个编译时就确定的常数),如果申请的空间超过栈的剩余空间时,将提示overflow。因此,能从栈获得的空间较小。
  • 堆:堆是向高地址扩展的数据结构,是不连续的内存区域。这是由于系统是用链表来存储的空闲内存地址的,自然是不连续的,而链表的遍历方向是由低地址向高地址。堆的大小受限于计算机系统中有效的虚拟内存。由此可见,堆获得的空间比较灵活,也比较大。

申请效率的比较 

  • 栈:由系统自动分配,速度较快。但程序员是无法控制的。
  • 堆:由new分配的内存,一般速度比较慢,而且容易产生内存碎片,不过用起来最方便.

分配方式

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

案例

void f()
{ 
    int* p=new int[5];
}

      这条短短的一句话就包含了堆与栈,看到new,我们首先就应该想到,我们分配了一块内存,那么指针p呢?他分配的是一块内存,所以这句话的意思就是:在栈内存中存放了一个指向一块堆内存的指针p。在程序会先确定在堆中分配内存的大小,然后调用operator new分配内存,然后返回这块内存的首地址,放入栈中,

原文地址:https://www.cnblogs.com/kaituorensheng/p/3450739.html