c++有五个内存分区:堆、栈、代码区、全局/静态存储区、常量存储区
1、堆(heap)
堆空间的大小不固定,可动态扩张或缩减,通常是由new分配的内存块,对应一个delete。如果未写释放,则在程序结束后,操作系统会自动回收。也有malloc,但主要在c中使用,释放时用free释放。
两者的差别:
-
malloc是C语言中的函数,而new是C++中的操作符。
-
malloc申请之后返回的类型是VOID*,而new返回的指针带有类型。
-
malloc只负责内存的分配而不会调用类的构造函数,而new不仅会分配内存,而且会自动调用类的构造函数。
2、栈(stack)
是用户存放程序临时创建的局部变量,也就是说我们函数括弧“{}”中定义的变量(但不包括static声明的变量,static意味着在数据段中存放变量)。除此以外,在函数被调用时,其参数也会被压入发起调用的进程栈中,并且待到调用结束后,函数的返回值也会被存放回栈中。由于栈的先进先出特点,所以栈特别方便用来保存/恢复调用现场。 整个程序的栈区的大小可以在编译器中由用户自行设定,默认的栈区大小为3M。
3、代码区
存储程序体中的二进制代码,比如写的函数都是在代码区。
4、全局/静态存储区
全局、静态数据存放在一起的,初始化的全局变量和静态变量是在一起的。未初始化的全局变量和静态变量是在相邻的空间中。
说明:全局变量和静态全局变量的存储方式是一致的,但是其区别在于,全局变量在整个源代码中都可以使用,而静态全局变量只能在当前文件中有效。比如我们的一个程序有5个文件,那么某个文件中申请了静态全局变量,这个静态全局变量只能在当前文件中使用,其他四个文件均不可以使用。而某个文件中申请了全局变量,那么其他四个文件中都可以使用该全局变量(只需要通过关键字extern申明一下就可以使用了)。事实上static改变了变量的作用范围。
5、常量存储区
存放字符串常量,程序结束后,由系统进行释放。比如我们定义char * p = “Hello World”; 这里的“Hello World”就是在字符串常量中,最终系统会自动释放。
内存分配的问题:
int a=1; a在栈区
char s[]="123"; s在栈区,“123”在栈区,其值可以被修改
char *s="123"; s在栈区,“123”在常量区,其值不能被修改
int *p=new int; p在栈区,申请的空间在堆区(p指向的区域)
int *p=(int *)malloc(sizeof(int)); p在栈区,p指向的空间在堆区
static int b=0; b在静态区