C++的内存模型
根据c++对象的生命周期不同,内存模型有三种不同的内存区域
- 自由存储区:局部非静态变量的存储区域,即栈
- 动态区:用new、malloc分配的内存,即堆
- 静态区:全局变量、静态变量,字符串常量存在的位置
代码虽然占内存,但不属于内存模型
栈和堆的区别
- 申请方式
栈由系统自动分配和管理,而堆是手动分配和管理- 扩展方向
栈从高地址向低地址扩展,堆是由低地址向高地址扩展- 程序局部变量使用的是栈空间,函数调用时兴参和返回值的压栈出栈也是栈空间,new和malloc使用的是堆空间
栈的效率高的原因
栈式操作系统提供的数据结构,计算机底层为栈提供了一系列的支持:分配专门的寄存器存储栈的地址,压栈和入栈有专门的指令执行。
C++的内存分区
- 栈:编译器自动分配释放,存放函数的参数值,局部变量的值
- 堆:手动分配和释放,需要通过new和malloc来申请内存,且必须在不使用时通过 delete和free释放
- 静态存储区:全局静态变量、局部静态变量、全局变量以及虚函数表
- 常量存储区:全局常量、函数指针
- 代码区:代码的只读区域
总结:无栈无法申请内存空间,无堆无法调用函数,无静态存储区无法多态,无常量存储区无函数。
在Linux系统中,程序在内存中的分布
- .txt 为编译后程序的主题,即程序的机器指令
- .data:全局初始化数据区/静态数据区,只初始化一次
- .bss: 未初始化数据区。在运行时改变其值
- 堆中保存动态分配的内存
- 栈用来进行函数调用,以及局部变量
为什么分成这么多区域
- 一个进程在运行过程中,代码是根据流程依次执行的,只需要访问一次,由于跳转和递归有可能使代码执行多次,而数据一般都需要访问多次,因此单独开辟空间以方便访问和节约空间。
- 临时数据及需要再次使用的代码在运行时放入栈区中,生命周期短。
- 全局数据和静态数据有可能在整个程序执行过程中都需要访问,因此单独存储管理。
- 堆区由用户自由分配,以便管理。
int a = 0; //a在全局已初始化数据区
char *p1; //p1在BSS区(未初始化全局变量)
int main(){
int b; //b在栈区
char str1='a' //字符常量,常量存储区(低地址)
char str2[] = "abc"; //数组变量,存储在栈区(高地址)
char *p1,*p2; //p1、p2在栈区
static int c =0; //C为(静态)数据,存在于已初始化数据区
p1 = (char *)malloc(10);//分配得来的10个字节的区域在堆区
p2 = (char *)malloc(20);//分配得来的20个字节的区域在堆区
free(p1);
free(p2);
}
char *str1='a'
char *str2='a'
char str3[] = "abc"
char str4[] = "abc"
str1==str2
str3!=str4