知识-了解C++的内存分配和回收

内容纲要

C++的内存分配和回收

摘自此文

数据结构中的堆和栈

数据结构 简介
是一种连续储存的数据结构,具有先进后出的性质。通常的操作有入栈(压栈),出栈和栈顶元素。想要读取栈中的某个元素,就是将其之间的所有元素出栈才能完成。
是一种非连续的树形储存数据结构,每个节点有一个值,整棵树是经过排序的。特点是根结点的值最小(或最大),且根结点的两个子树也是一个堆。常用来实现优先队列,存取随意。

程序运行的内存分配

内存空间 简介 分配
栈区 Stack memory内存空间由操作系统自动分配和释放 由程序自动向操作系统申请分配以及回收,速度快,使用方便,但程序员无法控制。若分配失败,则提示 栈溢出 错误
堆区 Heap Memory内存空间手动申请和释放的(常用new 程序员申请一块内存,当操作系统收到程序的申请时,会遍历一个记录空闲内存地址的链表,寻找第一个空间大于所申请空间的堆结点,然后将该结点从空闲结点链表中删除,并将该结点的空间分配给程序。分配的速度较慢,地址不连续,容易碎片化。此外,由程序员申请,同时也必须由程序员负责销毁,否则导致 内存泄露

《C++内存管理技术内幕》

根据《C++内存管理技术内幕》一书,在C++中,内存分成5个区,他们分别是堆,栈,自由存续区,全局/静态存续区,常量存续区。

  • 栈:内存由编译器在需要时自动分配和释放。通常用来存储局部变量和函数参数。(为运行函数而分配的局部变量、函数参数、返回地址等存放在栈区)。栈运算分配内置于处理器的指令集中,效率很高,但是分配的内存容量有限。

  • 堆:内存使用new进行分配,使用delete或delete[]释放。如果未能对内存进行正确的释放,会造成内存泄漏。但在程序结束时,会由操作系统自动回收。

  • 自由存储区:使用malloc进行分配,使用free进行回收。和堆类似。

  • 全局/静态存储区:全局变量和静态变量被分配到同一块内存中,C语言中区分初始化和未初始化的,C++中不再区分了。(全局变量、静态数据、常量存放在全局数据区)

  • 常量存储区:存储常量,不允许被修改。
      
    这里,在一些资料中是这样定义C++内存分配的,可编程内存在基本上分为这样的几大部分:静态存储区、堆区和栈区。他们的功能不同,对他们使用方式也就不同。

  • 静态存储区:内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在。它主要存放静态数据、全局数据和常量。

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

  • 堆区:亦称动态内存分配。程序在运行的时候用malloc或new申请任意大小的内存,程序员自己负责在适当的时候用free或 delete释放内存。动态内存的生存期可以由我们决定,如果我们不释放内存,程序将在最后才释放掉动态内存。 但是,良好的编程习惯是:如果某动态内存不再使用,需要将其释放掉,否则,我们认为发生了内存泄漏现象。

总结

int a = 0;   //全局初始化区
char *p1;    //全局未初始化区
int main()
{
    int b;               //栈
    char s[] = "abc";    //栈
    char *p2;            //栈
    char *p3 = "123456"; //123456\0在常量区,p3在栈上。
    static int c =0;    // 全局(静态)初始化区

    // 分配得来得10和20字节的区域就在堆区。
    p1 = (char *)malloc(10);
    p2 = (char *)malloc(20);
    strcpy(p1, "123456"); // 123456\0放在常量区,编译器可能会将它与p3所指向的"123456"优化成一个地方。 
}
void fn(){ 
    //在栈内存中存放了一个指向一块堆内存的指针p
    //程序会先确定在堆中分配内存的大小,然后调用 operator new分配内存
    //最后返回这块内存的首地址,放入栈中。
    int* p = new int[5];    //delete []p    释放指针数组
}

发表评论