当前位置: 首页 > article >正文

(c++)内存四区:1.代码区2.全局区(静态区)3.栈区4.堆区

//内存四区:1.代码区   2.全局区  3.栈区  4.堆区

1.放在代码区的有:1.写的代码:只读的、共享的、存放的二进制机器指令、由操作系统直接管理
2.放在全局区的有:1.全局的(变量或常量)  2.静态的(变量或常量)  3.字符串常量
3.在栈区的有:1.局部的(变量或常量)

注:1.函数形参也是局部的 2.main()函数内创建的变量也是局部变量

3.对于一个局部变量指针,若它指向的空间在栈区,不要返回这个指针。由于变量是局部变量,函数结束后局部变量的就自动释放了,这块地址上的空间你也不能再操作了,除非你返回的这个地址在堆区。

对于一个局部变量指针,若它指向的空间在堆区,可以返回这个指针。虽然函数结束后这个指针同样会被释放,但是已经将地址传递出去了,并且由于他的地址在堆区所以虽然函数结束了但是这块空间依然能够被操作。

以上两种情况下在函数内创建的指针,在函数结束后都被释放了,只不过前者返回出来的地址不能用了,后者返回出来的地址仍然可以操控。

关键在于:指针指向的地址空间在栈区还是堆区,在栈区则不要返回(返回了也不能操纵,这块空间,因为编译器自动释放了)、在堆区则可以。

4.放在堆区的有:利用new创建的数据。可以通过delete释放

创建的操作为:

int* p2 = new int(10);

    //new int(10)代表开辟一个堆区的空间并且赋值为10,整个表达式会返回这个空间的地址。
    //int* p创建一个指针p。
    //int* p=new int(10)  用创建的这个指针p来接收new int(10)返回的地址

以下代码在干嘛?在创建各种变量、常量、局部的、全局的、静态的,然后访问他们的内存地址。

注意!!!最后一个cout是为了演示delete后还要访问这个堆区的空间会引发的异常,读者使用代码时请给注释掉

#include<iostream>
using namespace std;

// 内存四区:1.代码区  2.全局区  3.栈区  4.堆区
//1.放在代码区的有:1.写的代码
//2.放在全局区的有:1.全局的(变量或常量)  2.静态的(变量或常量)  3.字符串常量
//3.在栈区的有:1.局部的(变量或常量),程序员创建,编译器自动释放
//4.放在堆区的有:1.new开辟的空间,由程序员创建和释放(整个程序运行完了也会自动释放)


//全局变量
int g_a = 0;
int g_b = 0;

//const修饰的全局变量
const int c_g_a = 0;
const int c_g_b = 0;

//static修饰的全局变量
static int s_g_a = 0;
static int s_g_b = 0;


int* func1()
{
	int a = 10;
	int* p1 = &a;
	return p1;
}

//利用new将数据放在堆区
int* func2()
{

	//new int(10)代表开辟一个堆区的空间并且赋值为10,整个表达式会这个空间的地址。
	//int* p创建一个指针p。
	//int* p=new int(10)  用创建的这个指针p来接收new int(10)返回的地址
	int* p2 = new int(10);

	return p2;
}

int main()
{


	//全局变量
	cout << "全局变量g_a的地址为:\t\t" << (int)&g_a << endl;
	cout << "全局变量g_b的地址为:\t\t" << (int)&g_b << endl;

	//静态变量 在普通变量前面加static,属于静态变量
	static int s_a = 0;
	static int s_b = 0;

	cout << "静态局部变量s_a的地址为:\t" << (int)&s_a << endl;
	cout << "静态局部变量s_b的地址为:\t" << (int)&s_b << endl;
	//
	cout << "静态全局变量s_g_a的地址为:\t" << (int)&s_g_a << endl;
	cout << "静态全局变量s_g_b的地址为:\t" << (int)&s_g_b << endl;


	//常量分为1.字符串常量2.const修饰的变量
	cout << "字符串常量的地址:\t\t" << (int)&"hello world" << endl;

	//const修饰的变量:1.修饰全局变量  2.修饰局部变量
	cout << "全局常量c_g_a的地址为:\t\t" << (int)&c_g_a << endl;
	cout << "全局常量c_g_b的地址为:\t\t" << (int)&c_g_b << endl;

	//修饰局部变量
	cout << endl;
	const int c_l_a = 0;
	const int c_l_b = 0;
	cout << "局部常量c_l_b的地址为:\t" << (int)&c_l_a << endl;
	cout << "局部常量c_l_b的地址为:\t" << (int)&c_l_b << endl;

	//创建普通局部变量
	int a = 0;
	int b = 10;

	cout << "局部变量a的地址为:\t" << (int)&a << endl;
	cout << "局部变量b的地址为:\t" << (int)&b << endl;
	cout << endl;

	//读取指向栈区空间指针的值(不能正常读取,部分编译器第一次可以正常读取,之后便不行了)
	int* p1 = func1();
	cout << "第一次读取指向栈区空间的指针的值:" << *p1 << endl;
	cout << "第二次读取指向栈区空间的指针的值:" << *p1 << endl;
	cout << endl;

	//读取指向堆区空间指针的值
	int* p2 = func2();
	cout << "第一次读取指向堆区空间的指针的值:" << *p2 << endl;
	cout << "第二次读取指向堆区空间的指针的值:" << *p2 << endl;

	//delete这个指针后再访问
	delete p2;
    //注意这行代码会引发异常!!!!使用代码请注释掉下面这个cout
	cout << "delete p2后读取指向堆区空间的指针的值:" << *p2 << endl;

	system("pause");
	return 0;
}

注意!!!最后一个cout是为了演示delete后还要访问这个堆区的空间会引发的异常,读者使用代码时请给注释掉

代码运行截图:

显然:

1.只要是带“全局”或者“静态”的都在一起,还有字符串常量也是。

2.只要是带“局部”的也都放在一起。

3.若局部变量指针指向的地址在栈区,则无法访问

4.若局部变量指针指向的地址在堆区,则能够正常访问

5.若将这个指针delete后便不能够正常访问了,也没有访问的权限。


http://www.kler.cn/a/326754.html

相关文章:

  • 【工具变量】中国制造2025试点城市数据集(2000-2023年)
  • Swift 开发教程系列 - 第5章:集合类型
  • Unity照片墙效果
  • Linux第三讲:环境基础开发工具使用
  • C++笔试题之实现一个定时器
  • node.js模块化分析
  • 日常工作技术点总结
  • 关于uniapp wifi调用走过的坑
  • 应用层协议 --- HTTP
  • 将Docker镜像推送到阿里云仓库,使用Docker-compose将mysql、redis、jar包整合在一起
  • spring如何解决循环依赖
  • NAND Flash虚拟层垃圾回收机制
  • 【微信小程序前端开发】入门Day01 —— 小程序页面组成、组件使用及协同开发发布指南
  • 深度探索与实战编码:利用Python与AWS签名机制高效接入亚马逊Product Advertising API获取商品详情
  • Web端云剪辑解决方案,提供前端产品源码
  • 使用 MongoDB 在 Spring Boot 中构建安全的 RBAC 系统
  • 【GESP】C++一级练习BCQM3016,初识输入
  • 实用工具推荐---- PDF 转换
  • 利用 Local Data 导入文件到 OceanBase 的方法
  • elasticsearch实战应用JAVA案例
  • Codeforces Round 975 (Div. 2)(A,B,C,D线段树解法,E)
  • 浅谈音频采集方案
  • Elasticsearch深度攻略:核心概念与实践应用
  • 前端使用 Konva 实现可视化设计器(23)- 绘制曲线、属性面板
  • vue3.0 + element plus 全局自定义指令:select滚动分页
  • 现代前端框架实战指南:React、Vue.js、Angular核心概念与应用