【C++第二阶段】内存模型—四区

程序的内存模型——四区

代码区

代码区(程序运行前):存放什么?——代码存放函数体的二进制代码,由操作系统进行管理。

将写的代码转换成二进制数据存储在代码区中,以便重复使用。

代码区特点:共享和只读。

代码区是共享的,共享的目的是对于频繁被执行的程序,只需要在内存中有一份代码即可。

代码区是只读的,使其只读原因是防止程序意外地修改了它的指令。

全局区

全局区(程序运行前):存放什么?

存放全局变量和静态变量以及常量。

全局变量:在main函数之外定义的变量。

静态变量:无论是否在main函数中定义的变量,前面加上static关键字修饰,都是静态变量。静态变量有什么特点?课程中没说,以下是Google得到结果。

常量:常量分为字符串常量和const修饰的变量。而const修饰的变量又分为const全局变量和const局部变量。只有const全局变量才会放在全局区,const局部变量会放在。

如何通过实验明显地观察出来?

实验思路为:分别设置几种变量:①全局变量;②静态变量—main函数中 | 外;③字符串常量;④const局部变量;⑤const全局变量。分别打印它们的地址。可以发现,局部变量(main函数中以及main函数中const修饰的变量)它们的地址是紧挨着的。而对于全局变量、静态变量、const全局变量,它们的地址是紧挨着。

通过该实验,就能明白,哪些变量|常量在一块,哪些是分开的。

以下是实验代码。

#include<iostream>
#include<string>
#include"print.h"
using namespace std;

//全局变量
int global_a = 10;
int global_b = 20;

//全局static变量
static int global_static_a = 10;
static int global_static_b = 20;

//全局const变量
const int global_const_a = 10;
const int global_const_b = 20;


int main() {

	//局部变量
	int local_a = 10;
	int local_b = 20;

	//局部static变量
	static int local_static_a = 10;
	static int local_static_b = 20;

	//局部const变量
	const int local_const_a = 10;
	const int local_const_b = 20;
		
	//常量


	//cout << "变量名称" << "\t\t" << "局部" << "\t\t" <<"\t\t" << "全局" << "\t\t" <<"\t\t" << endl;
	cout << "类型" << "\t\t\ta\t\t\tb" << endl;

	cout << "全局" << endl;
	cout << "全局变量" << "\t\t"<<(int)&global_a<<"\t\t"<<(int)&global_b<<endl;
	cout << "全局static变量" << "\t\t"<<(int)&global_static_a<<"\t\t"<<(int)&global_static_b<<endl;
	cout << "全局const变量" << "\t\t"<<(int)&global_const_a<<"\t\t"<<(int)&global_const_b<<endl;

	cout << "局部" << endl;
	cout << "局部变量" << "\t\t"<<(int)&local_a<<"\t\t"<<(int)&local_b<<endl;
	cout << "局部static变量" << "\t\t"<<(int)&local_static_a<<"\t\t"<<(int)&local_static_b <<endl;
	cout << "局部const变量" << "\t\t"<<(int)&local_const_a <<"\t\t"<<(int)&local_const_b<<endl;

	cout << "常量" << endl;
	cout << "常量" << "\t\t"<<(int)&"常量" << "\t\t"<<endl;

	system("pause");
}

实验打印输出

image-20240124150934402

通过观察,可以验证:

①无论static变量是否在全局还是在局部,它们都在全局区保存,因为都是941158开头的内存区。

②在全局区的变量类型有:全局变量,全局const变量,static变量,常量。

③const修饰局部变量,没有存放在全局区。const修饰全局变量,在全局区。

栈区

栈区(程序运行后):存放什么?

由编译器自动分配释放,存放函数的参数值,局部变量等。

注意,不要返回在栈区的数据指针。为什么?因为编译器会保留一次,保留的这次可以读取,可以打印输出。但也仅保留一次,之后再读取,打印输出就是乱码。

实验验证:思路:返回函数数据指针,并打印值。

代码:

#include<iostream>
#include<string>
using namespace std;

int* StackFunc2() {
	int a = 10;
	cout << "a的地址为:" << &a << endl;
	cout << "a的十进制地址为:" << (int) & a << endl;
	return &a;
}

int main() {

	//MemoryOfGlobal(&global_a, &global_b, &global_static_a, &global_static_b, &global_const_a, &global_const_b);
	int* ptr = StackFunc2();

	cout << "保留的这次为:" << *ptr << endl;
	cout << "第二次打印输出为:" << *ptr << endl;
	cout << "第三次打印输出为:" << *ptr << endl;


	system("pause");
}

实验结果:

image-20240124154208232

一次都没有保存。说明若返回局部变量值会出现问题——乱码。

若返回局部static变量呢?做法:修改a为static int

可以打印输出。

image-20240124154146791

堆区

堆区(程序运行后):存放什么?存放

由程序员分配和释放,若程序员不释放,程序结束时由操作系统回收。

由程序员自己索取的内存空间,若程序员没有自己释放,则在程序结束后由编译器自动释放。

如何自己创建内存空间?使用new关键词。new关键字返回的是内存的地址,所以要用指针数据类型接收它。

案例代码:

#include<iostream>
#include<string>
using namespace std;

int* UseNew() {
	int* a = new int(10);
	return a;
}

int main() {
	int* new_ptr = UseNew();
	cout << "使用新开辟的内存空间的值为:" << *new_ptr << endl;

	system("pause");
}

实验结束:

image-20240124154556930

四区存在意义:不同区域存放的数据,赋予不同的生命周期,灵活编程。

  • 10
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

HelpFireCode

随缘惜缘不攀缘。

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值