Day10.2021.11.14
面向对象
内存分区模型
程序执行时内存大方向划分四个区域
-
代码区:存放函数的二进制代码,由操作系统管理
-
全局区:存放全局变量,静态变量,常量
-
栈区:编译器自动分配释放,存放参数,局部变量等
-
堆区:由程序员分配释放,若不释放,由操作系统在程序结束时回收
意义:不同区域存放的数据有不同的生命周期,便于灵活编程
程序运行前
编译后,运行前,生成exe可执行程序,此时分为两个区域
-
代码区:存放CPU执行的机器指令(二进制010101这些)
特点:
共享(当点击exe文件,开始执行代码,开辟内存,而有些程序可以执行多次,比如我一直点exe,这种情况代码只会在内存中出现一次,而不会用重复代码占内存)
只读(防止程序意外地修改了指令),若代码可读可写,比如花10银币买道具,我改成10金币,拉了裤了
-
全局区:存放全局变量,静态变量
全局区还包含常量区,字符串常量和其他常量(用const修饰的变量)
特点:程序结束后由操作系统释放
#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
程序运行后
-
栈区:编译器自动分配释放,存放参数,局部变量等
注意:不要返回局部变量地址,栈区开辟的数据由编译器自动释放
#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; }
-
堆区:由程序员分配释放,若不释放,由操作系统在程序结束时回收
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可以一直使用。
可以重复输出的原因分析:
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