内存分区模型
c++程序在执行时,将内存划分为4个区域
代码区:存放函数体二进制代码,由操作系统管理
全局区:存放全局变量、静态变量及常量
栈区:由编译器自动分配释放,存放函数参数值、局部变量等
堆区:由程序员分配释放,若程序员不释放程序结束时由操作系统回收
内存四区意义:
不同区域存放的数据,赋予不同生存周期,编程会更灵活
1.程序运行前
在程序编译后,生成.exe可执行程序,未执行该程序前分为两个区域
代码区:
存放CPU执行的机器指令
代码区是共享的:对于频繁被执行的程序,只需要在内存中有一份代码即可
代码区是只读的:防止程序意外地修改了它的指令
全局区:
全局变量、静态变量(静态指在整个程序生命周期的地址静止不变)和常量存放于此
常量包含字符串常量和const修饰的全局变量
该区域数据在程序结束后由操作系统释放
#include<iostream>
#include<string>
using namespace std;
//全局变量
int g_a=10;
int g_b=10;
//const修饰全局变量(全局常量)
const int c_g_a=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;
//静态变量
static int s_a=10;
static int s_b=10;
cout<<"静态变量s_a的地址为:"<<(int)&s_a<<endl;
cout<<"静态变量s_b的地址为:"<<(int)&s_b<<endl;
//常量
//字符串常量
cout<<"字符串常量的地址为:"<<(int)&"Hello world!"<<endl;
//const修饰的变量
//const修饰全局变量
cout<<"全局常量c_g_a的地址为:"<<(int)&c_g_a<<endl;
//const修饰局部变量
const int c_l_a=10;
cout<<"局部常量c_l_a的地址为:"<<(int)&c_l_a<<endl;
return 0;
}
运行结果:
2.程序运行后
栈区:
由编译器自动分配释放,存放函数参数值,局部变量等
Attention:不要返回局部变量地址,因为栈区开辟的数据由编译器自动释放
#include<iostream>
using namespace std;
int *func(int b){ //形参也存于栈区
b=100;
int a=10; //局部变量,存于栈区
return &a; //返回局部变量地址(warning C4172: returning address of local variable or temporary)
}
int main(){
//接收func()的返回值
int *p=func(1);
cout<<*p<<endl; //第一次可打印正确数据是因为编译器做了保留
cout<<*p<<endl; //第二次该数据不再保留
return 0;
}
运行结果:
堆区:
由程序员分配释放,若程序员不释放,程序结束时由操作系统回收
c++中利用 new 在堆区中开辟内存,利用 delete 释放
语法: new 数据类型
new返回值为其数据类型的指针,因此在堆区创建数据后还要定义一个相应的指针接收
#include<iostream>
using namespace std;
//1.new的基本语法
int *func(){
//在堆区创建整型数据
int *p=new int(10); //new返回是该数据类型的指针
return p;
}
void test01(){
int *p_test01=func();
cout<<*p_test01<<endl;
cout<<*p_test01<<endl;
cout<<(int)p_test01<<endl;
int x=1;
cout<<"x位于栈区的地址为:"<<(int)&x<<endl;
delete p_test01; //利用delete释放堆区数据
cout<<*p_test01<<endl; //内存已经释放,该句非法
}
//2.在堆区利用new开辟数组
void test02(){
//在堆区创建10个整形数据数组
int *arr=new int[10];
for(int i=0;i<10;i++){
*arr=100+i;
cout<<"第"<<i<<"号数据为:"<<*arr<<endl;
cout<<"第"<<i<<"号数据位于堆区的地址为:"<<(int)arr<<'\t'
<<"arr位于栈区地址为:"<<(int)&arr<<endl;
arr++;
}
delete[]arr; //释放堆区数组时,要加[]
}
int main(){
test01();
test02();
return 0;
}
运行结果: