在c++中,内存分成以下几个区:栈、堆、自由储存区、全局/静态存储区和常量存储区
1、栈(stack)
由编译器在需要的时候自动分配,不需要的时候自动清除的储存区。在分配和清除是都不需要程序员干预,
全由编译器进行管理。这个区通常存放的变量为局部变量、函数形参等
2、堆(heap)
一般由程序员分配和释放,如果程序员没有释放,那么在程序结束后有操作系统自动回收。这个去是那些由
new分配的内存块,它们的释放编译器不去管,由程序员去进行控制。一般一个new就要对于一个delete。
3、自由储存区(free store)
就是那些有malloc等分配的内存块,它和堆是十分相似的,不过他是用free来释放内存的。
4、全局/静态区(static)
全局变量和静态变量被分配到同一块内存中,在以前的C语言中,全局变量由分为初始化的哈为初始化的,
在C++里面没有这个分区了,他们共同占用同一块内存区。程序结束后有系统自动释放。
5、常量储存区
这是一款比较特殊的储存区,它们里面存放的是常量。
对于上面的内存分区,关于new和malloc在内存的分区有些争议。有些资料说new和malloc都是放在堆中
的,也有些资料说malloc放在堆中,new放在自由储存区中的。鄙人目前暂时也找不到权威的资料,希望
大家可以分享一下自己的见解。
另外一个比较重要的问题就是堆和栈的区别,它们的区别主要有一下几点:
1、管理方式不同
对于栈来讲,是由编译器自动管理,无需我们手工控制;对于堆来说,释放工作由程序员控制,容易产
生内存泄露。
2、空间大小不同
一般来讲在32位系统下,堆内存可以达到4G的空间,从这个角度来看堆内存几乎是没有什么限制的。但
是对于栈来讲,栈的大小是2M(也有的说是1M,总之是一个编译时就确定的常数),如果申请的空间超
过栈的剩余空间时,将提示溢出。因此,能从栈获得的空间较小。
3、碎片产生不同
对于堆来讲,频繁的new/delete势必会造成内存空间的不连续,从而造成大量的碎片,使程序效率降低。
对于栈来讲,则不会存在这个问题,因为栈是先进后出的队列,他们是如此的一一对应,以至于永远都
不可能有一个内存块从栈中间弹出,在他弹出之前,在他上面的后进的栈内容已经被弹出
4、生长方向不同
对于堆来讲,生长方向是向上的,也就是向着内存地址增加的方向;对于栈来讲,它的生长方向是向下
的,是向着内存地址减小的方向增长。
5、分配方式不同
堆都是动态分配的,没有静态分配的堆。栈有2种分配方式:静态分配和动态分配。静态分配是编译器
完成的,比如局部变量的分配。动态分配由alloca函数进行分配,但是栈的动态分配和堆是不同的,他
的动态分配是由编译器进行释放,无需我们手工实现。
6、分配效率不同
栈是机器系统提供的数据结构,计算机会在底层对栈提供支持:分配专门的寄存器存放栈的地址,压
栈出栈都有专门的指令执行,这就决定了栈的效率比较高。堆则是C/C++函数库提供的,它的机制是
很复杂的,例如为了分配一块内存,库函数会按照一定的算法(具体的算法可以参考数据结构/操作
系统)在堆内存中搜索可用的足够大小的空间,如果没有足够大小的空间(可能是由于内存碎片
太多),就有可能调用系统功能去增加程序数据段的内存空间,这样就有机会分到足够大小的内存,
然后进行返回。显然,堆的效率比栈要低得多。
说了那么多,举一个例子来补充说明一下:
int i=10;//全局/静态区(static)
int j;//全局/静态区(static)
main()
{
int x;//栈
char s[]="string";//栈
char *p1;//栈
char *p2="string";//p2在栈上,“string”在常量区
char *p3=new[5];//p3在栈上,在栈内存中存放了一个指向一块堆内存的指针p3
}
习题练兵一下:
Class A{}
void function(A a1)
{
A a2=a1;
}
main()
{
A a3;
A *a4=new A;
}
请问a1 a2 a3 a4 这四个变量是在内存的哪些区?