首页 > 技术文章 > Day10.11.面向对象内存分区,new,引用

ayuanstudy 2021-11-18 22:21 原文

Day10.2021.11.14

面向对象

内存分区模型

程序执行时内存大方向划分四个区域

  1. 代码区:存放函数的二进制代码,由操作系统管理

  2. 全局区:存放全局变量,静态变量,常量

  3. 栈区:编译器自动分配释放,存放参数,局部变量等

  4. 堆区:由程序员分配释放,若不释放,由操作系统在程序结束时回收

意义:不同区域存放的数据有不同的生命周期,便于灵活编程

程序运行前

编译后,运行前,生成exe可执行程序,此时分为两个区域

  1. 代码区:存放CPU执行的机器指令(二进制010101这些)

特点:

共享(当点击exe文件,开始执行代码,开辟内存,而有些程序可以执行多次,比如我一直点exe,这种情况代码只会在内存中出现一次,而不会用重复代码占内存)

image-20211114154111439

只读(防止程序意外地修改了指令),若代码可读可写,比如花10银币买道具,我改成10金币,拉了裤了

  1. 全局区:存放全局变量,静态变量

全局区还包含常量区,字符串常量和其他常量(用const修饰的变量)

特点:程序结束后由操作系统释放

image-20211114174244947

image-20211114174126928

 #include "methodState.h"
 //全局区:全局变量,静态变量,常量
 //全局变量
 int g_a = 10;
 int g_b = 10;
 //const修饰的全局变量(全局常量)
 const int con_a = 10;
 const int con_b = 10;
 int main() {
     //普通局部变量
     int a = 10;
     int b = 10;
     //静态变量
     static int s_a = 10;
     static int s_b = 10;
     //常量:字符串常量,const修饰的变量
     //字符串常量
     //注意这里不能写string a="xxxxx";这是局部变量
     cout << "字符串常量的地址:" << (int)&"cplusplus" << endl;
     //const修饰的变量
     cout << "const修饰的全局变量(全局常量)的地址:" << (int)&con_a << endl;
     cout << "const修饰的全局变量(全局常量)的地址:" << (int)&con_b << endl;
     //const修饰的局部变量(局部常量)
     const int con_in_a = 10;
     const int con_in_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;
     cout << "静态变量s_a的地址:" << (int)&s_a << endl;
     cout << "静态变量s_b的地址:" << (int)&s_b << endl;
     cout << "const修饰的局部变量的地址(局部常量)" << (int)&con_in_a << endl;
     cout << "const修饰的局部变量的地址(局部常量)" << (int)&con_in_b << endl;
     system("pause");
     return 0;
 }

  

Day11.2021.11.16

程序运行后

  1. 栈区:编译器自动分配释放,存放参数,局部变量等

注意:不要返回局部变量地址,栈区开辟的数据由编译器自动释放

 #include"methodState.h"
 /*栈区:编译器自动分配释放,存放参数,局部变量等
 注意:不要返回局部变量地址,栈区开辟的数据由编译器自动释放*/int* fun() {//形参也放栈区
     int a = 10;//局部变量存在栈里,函数执行完自动释放,所以拿不到数据
     return &a;
 }
 int main() {
 ​
     int* p = fun();
     //第一次编译器怕你误操作,就保留了一次数据
     cout << *p << endl;//10 编译器:我为这傻子操碎了心
     cout << *p << endl;//2069866888:不再保留
 ​
     system("pause");
     return 0;
 }

 

  1. 堆区:由程序员分配释放,若不释放,由操作系统在程序结束时回收

 int* fun1() {
     //用new开辟堆存放数据
     //指针也是局部变量,存放在栈区;指针指向的数据存放在堆区
     int* p = new int(10);
     return p;
 }
 int main() {
     int* p = fun1();
     cout << *p << endl;
     system("pause");
     return 0;
 }

 

堆区的数据不会改变,在栈上创建的指针指向堆区的内存,栈上的指针会释放,但是堆区的数据不会释放。每次指向都是。main 中的p指向的就是堆区变量的地址,因为不会释放,所以p可以一直使用。

可以重复输出的原因分析:

image-20211118202703714

new关键字使用

 int* fun1() {
     //new返回的是数据类型的指针
     int* p = new int(10);
     return p;
 }
 int main() {
     int* p = fun1();
     cout << *p << endl;
     cout << *p << endl;
     delete p;
     //cout << *p << endl;内存已经被释放,提示未初始化内存p
     system("pause");
     return 0;
 }

  

new关键字在堆区开辟数组

 
int* arrays() {
     int* arrays=new int[10];
     arrays[1] = 3;
     return arrays;
 }
 int main() {
     int* p = arrays();
     for (int i = 0; i < 10; i++) {
         cout << p[i] << endl;
     }
     delete[] p;//释放数组需要加[]
     cout << p[1] << endl;
     system("pause");
     return 0;
 }

  

引用

给变量起别名

 
 //引用:类型 &别名=原名
     int oldName = 20;
     int& newName = oldName;
     newName = 40;
     cout << oldName << endl;//40
     cout << newName << endl;//40

  

image-20211118221800758

P89结束

来源:b站黑马

推荐阅读