C++的内存分区

C++的内存划分为栈区、堆区、全局区/静态区、字符串常量和代码区。

栈区###

由系统进行内存的管理。
主要存放函数的参数以及局部变量。在函数完成执行,系统自行释放栈区内存,不需要用户管理。整个程序的栈区的大小可以在编译器中由用户自行设定,VS中默认的栈区大小为1M,可通过VS手动更改栈的大小。64bits的Linux默认栈大小为10MB,可通过ulimit -s临时修改。

栈是一种连续储存的数据结构,具有先进后出的性质。通常的操作有入栈(圧栈)、出栈和栈顶元素。想要读取栈中的某个元素,就要将其之前的所有元素出栈才能完成。由程序自动向操作系统申请分配以及回收,速度快,使用方便,但程序员无法控制。若分配失败,则提示栈溢出错误。注意,const局部变量也储存在栈区内,栈区向地址减小的方向增长。

堆区###

由用户手动申请,手动释放,若不手动释放,程序结束后由系统回收。
在C中使用malloc,在C++中使用new(当然C++中也可以使用malloc)。
说明:new操作符本质上还是使用了malloc进行内存的申请。
1)malloc是C语言中的函数,而new是C++中的操作符。
2)malloc申请之后返回的类型是VOID*,而new返回的指针带有类型。
3)malloc只负责内存的分配而不会调用类的构造函数,而new不仅会分配内存,而且会自动调用类的构造函数。

堆是一种非连续的树形储存数据结构,每个节点有一个值,整棵树是经过排序的。特点是根结点的值最小(或最大),且根结点的两个子树也是一个堆。常用来实现优先队列,存取随意。堆内存:程序员向操作系统申请一块内存,当系统收到程序的申请时,会遍历一个记录空闲内存地址的链表,寻找第一个空间大于所申请空间的堆结点,然后将该结点从空闲结点链表中删除,并将该结点的空间分配给程序。分配的速度较慢,地址不连续,容易碎片化。此外,由程序员申请,同时也必须由程序员负责销毁,否则则导致内存泄露。

全局/静态区###

全局、静态数据存放在一起的,初始化的全局变量和静态变量是在一起的。
未初始化的全局变量和静态变量是在相邻的空间中。

字符串常量区###

存放字符串常量,程序结束后,由系统进行释放。
比如我们定义char * p = “Hello World”; 这里的“Hello World”就是在字符串常量中,最终系统会自动释放。

代码区###

存放程序体的二进制代码。
比如我们写的函数,都是在代码区的。

int a = 0;//全局变量(全局/静态区)
char *p1; //编译器默认初始化为NULL,全局变量(全局/静态区)
void main()
{
    int b; //局部变量(栈)
    char s[] = "abc";//栈
    char *p2 = "123456";//123456在字符串常量区,p2在栈上
    static int c =0; //c静态变量(全局/静态区),0为文字常量(代码区)
    const int d=0; //栈
    static const int d;//静态常量区(全局/静态区)
    p1 = (char *)malloc(10);//分配得来得10字节在堆区。
    strcpy(p1, "123456"); //123456放在字符串常量区,编译器可能会将它与p2所指向的"123456"优化成一个地方
}

参考##

madonion
Dablelv的博客专栏
ChenZhongzhou