内存分区模型
程序运行前有两个区
1.代码区
在内存中存放二进制代码,生成二进制文件,只读(防止被修改)
2.全局区
全局变量 静态变量 常量存放在此,在程序结束后由操作系统释放
int main()
{
//创建普通局部变量
int a=10;
int b=10;
cout<<"局部变量a的地址为:"<<(int)&a<<endl;
cout<<"局部变量b的地址为:"<<(int)&b<<endl;
return 0;
}
//全局变量
int g_a=10;
int g_b=10;
int main()
{
//创建普通局部变量
int a=10;
int b=10;
cout<<"局部变量a的地址为:"<<(int)&a<<endl;
cout<<"局部变量b的地址为:"<<(int)&b<<endl;
cout<<"全局变量g_a的地址为:"<<(int)&g_a<<endl;
cout<<"全局变量g_b的地址为:"<<(int)&g_b<<endl;
return 0;
}
效果如图:
image.png
局部变量和全局变量的地址不在一个段里
静态变量
static int s_a=10;
static int s_b=10;
效果如图,全局变量和静态变量的地址很近
image.png
常量、字符串常量也跟静态变量和局部变量的内存地址很近
const 修饰的变量
1.const 修饰的全局变量
const int c_g_a=10;
const int c_g_b=10;
int main(){}
2.const 修饰的局部变量
int main()
{
const int c_l_a=10;
const int c_l_b=10;
}
效果如图
image.png
所以局部变量和const修饰的局部变量(局部常量)不在全局区
全局变量、静态变量(static关键字)、常量(字符串常量和const修饰的全局常量)
程序运行后的区域
1.栈区
编译器自动分配释放,存放函数的参数值、局部变量等
在代码编写中不要返回局部变量的地址,因为栈区的数据由编译器释放
int * func(int b)
{
b=100;形参数据也会放在栈区u
int a =10;//局部变量 存放在栈区 栈区的shu
return &a;//返回局部变量地址
}
int main()
{
int *p=func();
cout<<*p<<endl;//第一次可以打印正确的数字是因为编译器做了一个保留
cout<<*p<<endl;
}
效果如图
image.png
第一次能返回,第二次不能,因为编译器做了一个保留,所以尽量不要返回局部变量的地址,但不管对错都是误操作!因为内存已经被释放了
2.堆区
由程序员分配释放,若程序员不释放,程序结束时由操作系统回收
在c++主要利用new在堆区开放内存
int * func()
{
//利用new关键字,可以将数据开辟到堆区
//指针本质也是局部变量,放在栈上,指针保存的数据放在堆区,所以返回p而不是*p
int *p = new int (10);//new函数返回地址,所以用指针接收
int a=10;
return p;//我不释放,p一直存在,不管打印机次
}
int main()
{
int *p=func();
return 0;
cout<<*p<<endl;//能够成功输出10
}
原理如图
image.png