C++核心(面向对象)
内存分区模型
C++程序执行时,将内存分为4个区域:
- 代码区:存放函数体的二进制代码,由操作系统管理
- 全局区:存放全局变量、静态变量和常量(字符串常量和其他常量)
- 栈区:内存由编译器自动分配和释放,存放函数的参数值和局部变量
- 堆区:内存由程序员分配和释放,程序员不释放,程序结束时会由操作系统回收
内存分区的意义:不同区域存放的数据,被赋于不同的生命周期,可灵活编程
1.程序运行前
程序编译后,生成exe可执行文件,未执行程序前,将内存分为两个区域:代码区和全局区。
- 代码区:存放CPU执行的机器指令;具有共享和只读的特点
- 全局区:存放全局变量、静态变量和常量;在程序结束后,内存由操作系统释放
#include <iostream>
using namespace std;
int a = 10, b = 20; //全局变量
const int e = 60; //const修饰的全局变量
int main()
{
static int c = 30; //静态变量
static int d = 40;
const int f = 50; //const修饰的局部变量
int g = 70, h = 80; //局部变量
cout<<&a<<" "<<&b<<endl; //全局变量在内存中的地址编号
cout<<&c<<" "<<&d<<endl; //静态变量在内存中的地址编号
cout<<&"Hello World"<<endl; //字符串常量在内存中的地址编号
cout<<&e<<endl; //const修饰的全局变量在内存中的地址编号
cout<<&f<<endl; //const修饰的局部变量在内存中的地址编号
cout<<&g<<" "<<&h<<endl; //局部变量在内存中的地址编号
return 0;
}
总结:C++程序运行前分为代码区和全局区,代码区存放CPU执行的机器指令,代码区的特点是共享性和只读性;全局区存放全局变量、静态变量和常量(const修饰的全局变量和字符串常量),其中const修饰的局部变量存放在栈区。
2.程序运行后
栈区数据的内存由编译器分配与释放,注:局部变量存放在栈区,局部变量的地址不能返回;堆区利用new和delete关键字分配和释放内存。
#include <iostream>
using namespace std;
int * func1()
{
int a = 10;
return &a; //在栈区分配内存,调用完函数后内存释放,此数据已经不存在,不能作为返回值
}
int * func2()
{
int *p = new int(10); //指针为局部变量,存放在栈上,而数据10存放在堆上
return p;
}
int main()
{
int *p, *q;
p = func1();
cout<<*p<<endl; //10,第一次返回是编译器为用户保留的值,但实际操作已经非法
cout<<*p<<endl; //0,第二次无保留
q = func2(); //堆区分配内存,调用函数后只是存放数据地址的指针地址释放,数据地址仍存在,可以返回
cout<<*q<<endl; //10
cout<<*q<<endl; //10
delete q; //释放堆上内存
cout<<*q<<endl; //非法
int * arr = new int[10]; //数组
int i;
for(i = 0; i < 10; i++)
{
arr[i] = 100 + i;
}
for(i = 0; i < 10; i++)
{
cout<<arr[i]<<" ";
}
cout<<endl;
delete arr;
return 0;
}
总结:程序运行后,内存分为栈区和堆区,栈区存放局部变量和函数参数,数据内存由编译器分配和释放;堆区内存由程序员分配和释放,可通过new和delete关键字来在堆区分配内存和释放内存。