C++ 黑马 内存分配模型
一, 内存分配模型
内存总共有四个分区
1 代码区
主要用来存储二进制代码,由操作系统进行管理
2 栈区
由编译器自己进行释放和分配,例如函数的传递的参数,局部变量,const修饰的局部常量等等....
3 堆区
由程序员自己分配和释放,如果程序员没有进行释放,则由操作系统到最后自行释放
4 全局区
主要存储全局变量,静态常量,字符串常量和全局常量(const修饰)
分区的意义:
不同区域存放不同的数据,可以控制这些数据不同的生命周期,使得内存灵活
二, 代码区和全局区
代码区和全局区是在程序运行之前就已经开始分区了
1. 代码区
主要存放的是CPU执行的机器指令
代码区的特点
1 共享性:在我们点击编译运行按钮的时候都会生成一个可执行的.exe文件,这个文件进行多次点击会弹出多个窗口,然后这里面的数据是互通公用的,计算机并不会重新开辟一个内存再次进行存储
2 只读性:比如充值系统的数据是不可以随意更改的,要是给予更改的话,商家无疑是亏损很大的,所以这个充值系统不可以随意的更改
2. 全局区
主要存放全局变量,静态常量,字符串常量和全局常量(const修饰)
全局变量-----不在函数体内部的变量
静态常量-----加上static关键字的变量
字符串,const修饰的全局常量
以上可以根据设置变量在不同的区域,来输出他们对应的地址来观察判断是否是属于同一区域的
#include<iostream>using namespace std;//全局变量
int a;//const 修饰的全局常量
const int b1 = 0;
const int b2 = 0;int main() {//const修饰的局部变量const int a1 = 0;const int a2 = 0;//static修饰的静态变量static int c1;static int c2;cout << "字符串地址:" << (int)&"hello world" << endl;cout << "static地址:" << (int)&c1 << endl;cout << "static地址:" << (int)&c2 << endl;cout << "const局部地址:" << (int)&a1 << endl;cout << "const局部地址:" << (int)&a2 << endl;cout << "const全局地址:" << (int)&b1 << endl;cout << "const全局地址:" << (int)&b2 << endl;}
字符串地址:995208456
static地址:995221940
static地址:995221944
const局部地址:-2081424876
const局部地址:-2081424844
const全局地址:995208112
const全局地址:995208116D:\porject\C++\x64\Debug\C++.exe (进程 3144)已退出,代码为 0 (0x0)。
要在调试停止时自动关闭控制台,请启用“工具”->“选项”->“调试”->“调试停止时自动关闭控制台”。
按任意键关闭此窗口. . .
可以看到运行出来的控制窗口显示的地址字符串,static,const修饰的全局地址都是十分接近的,但是const修饰的局部地址是离很远的,这么说明const修饰的局部变量不是在全局区
三,栈区和堆区
栈区和堆区,这两个区域是程序运行后才产生的
1. 栈区
栈区是由编译器自己分配和释放的,一般都是局部变量,函数的传参值...
注意事项:1 不要返回局部变量的地址,栈区开辟的数据由编译器自己决定释放
#include<iostream>using namespace std;int* fun() {int b = 10;return &b;
}int main() {int* p = fun();cout << *p << endl;cout << *p << endl;cout << *p << endl;cout << *p << endl;cout << *p << endl;cout << *p << endl;int a = 1;cout << *p << endl;return 0;
}
当我们不用VS2022,用Dev-C++来运行这个代码的时候,运行出来的结果是这样的
10
0
0
0
0
0
0--------------------------------
Process exited after 0.791 seconds with return value 0
请按任意键继续. . .
运行出来的结果后面都是未知量,这个时候我们可以知道,经典的C++编译器只会给我们保留一次这个值,并不会一直保留,所以后面答应出来的值都是0
2. 堆区
堆区的知识点我们只需要知道,这个区域是我们程序员自己去释放和开辟区域的,然后C++喜欢用new运算符来进行开辟内存和释放内存
new运算符的使用
1. 利用new运算符开辟一个变量并且赋值
int* p = new int(10);
delete p;
2. 利用new运算符开辟一个数组
int* p = new int[10];
delete []p;
四, 总结
1 内存的分区类型
1 栈区 2 代码区 3 全局区 4 堆区
2 每个内存分区的作用
(づ。◕‿‿◕。)づ 代码区:
(a) 主要存放二进制的机器指令
(b) 两个特点:共享和只读特性
(ノ◕ヮ◕)ノ:・゚✧ 全局区:
(a) 主要存放全局变量,静态常量,const修饰的全局常量,需要注意的是const修饰的常量不是存放在全局区域,可以通过打印对应的地址来判断他们的分区是否一致
(。・ω・。)ノ♡ 栈区:
(a) 栈区主要是编译器自己进行释放和分配内存,常见的由函数传递的参数,局部变量...等一系列生命周期较短的变量
Σ(°△°|||)︴ 堆区:
(a) 堆区主要是程序员自己进行分配和释放内存,最后没有释放的内存,等到程序结束由操作系统进行释放内存
3 new操作运算符的使用
主要就是分配变量和数组在堆区
int* p = new int(10);
delete p;
int* p = new int[10];
delete []p;