【C++】C++核心编程(一)---内存四区

news2024/12/26 14:20:54

C++程序在执行时,将内存大方向划分为4个区域

  1. 代码区
    存放函数体的二进制代码,由操作系统进行管理
  2. 全局区
    存放全局变量和静态变量以及常量(字符串常量、全局常量)
  3. 栈区
    由编译器自动分配释放,存放函数的参数值、局部变量等
  4. 堆区
    由程序员分配和释放,若程序不释放,程序结束时由操作系统回收

在这里插入图片描述

内存四区的意义:不同区域存放的数据,赋予不同的生命周期,给我们更灵活的编程创造条件。

1.程序运行前:

在程序编译后,生成了exe可执行程序,未执行该程序前分为2个区域(代码区、全局区)

  1. 代码区
    存放CPU执行的机器指令
    代码区是共享的,共享的目的是对于频繁被执行的程序,只需要在内存中有一份代码即可
    代码区是只读的,使其只读的原因是防止程序意外地修改了它的指令
  2. 全局区
    全局变量和静态变量存放在此
    全局区还包含了常量区,字符串常量和其他常量也存放在此
    该区域的数据在程序结束后由操作系统释放
  • 案例演示:
#include <iostream>
using namespace std;

// 全局区:全局变量、静态变量(static 数据类型 变量名)、常量(字符串常量、全局常量(const修饰的全局变量))
// 不在全局区中的:局部变量、const修饰的局部变量(局部常量)

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

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

int main() {

	// 局部变量
	int local_a = 10;
	int local_b = 20;
	cout << "局部变量a的内存地址为:" << (int)&local_a << endl;
	cout << "局部变量b的内存地址为:" << (int)&local_b << endl;

	cout << "全局变量a的内存地址为:" << (int)&global_a << endl;
	cout << "全局变量b的内存地址为:" << (int)&global_b << endl;

	// 静态变量
	static int a = 10;
	static int b = 20;
	cout << "静态变量a的内存地址为:" << (int)&a << endl;
	cout << "静态变量b的内存地址为:" << (int)&b << endl;

	// 常量
	// 字符串常量
	cout << "字符串常量的内存地址为:" << (int)&"nining" << endl;
	// 全局常量
	cout << "全局常量a的内存地址为:" << (int)&global_const_a << endl;
	cout << "全局常量b的内存地址为:" << (int)&global_const_b << endl;

	// 局部常量
	const int local_const_a = 10;
	const int local_const_b = 20;
	cout << "局部常量a的内存地址为:" << (int)&local_const_a << endl;
	cout << "局部常量b的内存地址为:" << (int)&local_const_b << endl;

	system("pause");
	return 0;
}
  • 输出结果:
局部变量a的内存地址为:16776620
局部变量b的内存地址为:16776608
全局变量a的内存地址为:10862592
全局变量b的内存地址为:10862596
静态变量a的内存地址为:10862600
静态变量b的内存地址为:10862604
字符串常量的内存地址为:10853380
全局常量a的内存地址为:10853168
全局常量b的内存地址为:10853172
局部常量a的内存地址为:16776596
局部常量b的内存地址为:16776584
请按任意键继续. . .

我们可以看到全局变量、静态变量、字符串常量、全局常量(存放在全局区)的内存地址都很相近,同时局部变量、局部常量(存放在栈区)的内存地址也很相近,存放在全局区的数据内存地址与存放在栈区的数据内存地址具有较大的差别。

2.程序运行后:

  1. 栈区
    由编译器自动分配释放,存放函数的参数值,局部变量等
    注意:不要返回局部变量的地址,栈区开辟的数据由编译器自动释放
  • 案例演示:
#include <iostream>
using namespace std;

// 创建一个函数,返回局部变量的地址
int* func(int b) //形参数据也放在栈区
{
	b = 100;
	int a = 10; //局部变量 存放在栈区,栈区的数据在函数执行完后自动释放
	return &a;
}

int main() {

	int* p = func(1);
	cout << *p << endl; //第一次能够正确的打印,是因为编译器对释放的数据进行了一次保留
	cout << *p << endl; //第二次出现乱码,也就是不能够正确地打印数据,是因为编译器不再保留数据了

	system("pause");
	return 0;
}
  • 输出结果:
10
16584764
请按任意键继续. . .
  1. 堆区
    由程序员分配释放,若程序员不释放,程序结束时由操作系统回收,在C++中主要利用new关键字在堆区开辟内存
    new操作符
    堆区开辟的数据由程序员手动开辟、手动释放,开辟数据利用操作符new
    语法1:数据类型 * p = new 数据类型(初始值)
    利用new创建的数据,会返回该数据对应的类型的指针
    语法2:数据类型 * arr = new 数据类型[数组长度]
    delete操作符
    堆区开辟的数据由程序员手动开辟、手动释放,释放利用操作符delete
    语法1:delete p;
    语法2:delete[] arr;
  • 案例演示:
#include <iostream>
using namespace std;

/*
new int(10);
delete 变量名; 
nem int[10];
delete [] 变量名;
*/

int* func()
{
	// 利用new关键字可以将数据开辟到堆区
	// 指针,在此本质上也是局部变量,放在栈上,指针保存的数据是放在了堆区
	int* p = new int(10);
	return p;
}

void func2()
{
	// 利用new关键字开辟一个数组到堆区
	int* arr = new int[10]; // 10代表数组有10个元素

	for (int i = 0; i < 10; i++)
	{
		arr[i] = i + 100;
	}

	for (int i = 0; i < 10; i++)
	{
		cout << arr[i] << endl;
	}

	// 释放堆区数组
	// 释放的时候要加上一个中括号
	delete[] arr;
}

int main() {
	// 在堆区开辟数据
	int* p = func();
	cout << *p << endl;
	cout << *p << endl;

	// 如果想要释放堆区的数据,利用关键字 delete
	delete p;
	// cout << *p << endl; // 已经将数据释放了,如果再访问将会报错

	func2();

	system("pause");
	return 0;
}
  • 输出结果:
10
10
100
101
102
103
104
105
106
107
108
109
请按任意键继续. . .

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/403781.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

jenkins问题

目录 python 不是内部或外部命令&#xff0c;也不是可运行的程序 ‘cmd’ 不是内部或外部命令&#xff0c;也不是可运行的程序或批处理文件。 git 不是内部或外部命令&#xff0c;也不是可运行的程序或批处理文件。 pywintypes.com_error: (-2147024891, ‘拒绝访问。’, None,…

Qt实用技巧:Qt中浮点数的相等比较方式(包括单精度和双精度)

若该文为原创文章&#xff0c;转载请注明原文出处 本文章博客地址&#xff1a;https://hpzwl.blog.csdn.net/article/details/129464152 红胖子(红模仿)的博文大全&#xff1a;开发技术集合&#xff08;包含Qt实用技术、树莓派、三维、OpenCV、OpenGL、ffmpeg、OSG、单片机、软…

Spring——AOP切入点表达式和AOP通知类型

切入点:要进行增强的方法 切入点表达式:要进行增强的方法的描述式 第一种方法的本质是基于接口实现的动态代理(jdk) 第二种是基于cglib实现的动态代理 AOP切入点表达式 而需要加载多个切入点时&#xff0c;不可能每个切入点都写一个切入点表达式 例子 下面的代理描述的是匹配…

条件语句(分支语句)——“Python”

各位CSDN的uu们你们好呀&#xff0c;最近总是感觉特别特别忙&#xff0c;但是却又不知道到底干了些什么&#xff0c;好像啥也没有做&#xff0c;还忙得莫名其妙&#xff0c;言归正传&#xff0c;今天&#xff0c;小雅兰的内容还是Python呀&#xff0c;介绍一些顺序结构的知识点…

Hadoop学习:Yarn

1.YARN介绍 一个通用的资源管理系统和调度平台 YARN不分配磁盘&#xff0c;由HDFS分配 相当于一个分布式的操作系统平台&#xff0c;为上层MR等计算程序提供运算所需要的资源&#xff08;内存、CPU等&#xff09; 2.YARN三大组件 不要忘记AppMaster&#xff0c;他是程序内部…

Android 进程间通信机制(二) mmap 原理

一. 前言 Binder中一次拷贝的实现就是利用mmap(memory mapping)内存映射机制,我们来看看它的工作原理. 二. 参考文章 下面这几篇文章建议先好好阅读一下,都是总结的很好的文章, 每个人理解可能不一样 笔者也是看了好多博客文章和B站视频讲解, 然后加上自己的理解后 输出的一…

程序的编译和链接

程序的编译和链接程序的编译和链接程序的两种环境翻译环境详解编译和链接预处理编译汇编链接运行环境程序的编译和链接 程序的两种环境 在ANSI C的任何一种实现中&#xff0c;存在两个不同的环境。 第1种是翻译环境&#xff0c;在这个环境中源代码被转换为可执行的机器指令。 …

《数据分析-JiMuReport04》JiMuReport报表设计入门介绍-页面优化

报表设计 2 页面优化 如上图所示的报表&#xff0c;仅仅是展示数据&#xff0c;不过这样看起来似乎太草率了&#xff0c;所以再优化一下吧 保存报表后&#xff0c;在积木报表中就可以看到对应的报表文件 此时我们如果还需要编辑报表&#xff0c;就点击这个报表即可 2.1 居中…

如何设计企业节点的『工业互联网标识解析系统』

一、『星火 链网』体系架构 『星火 链网』以节点形式进行组织互联互通&#xff0c;其中包括三类节点&#xff1a;超级节点、骨干节点、业务节点。 其底层采用“1N”主从链群架构&#xff0c;支持同构和异构区块链接入主链。在全国重点区域部署『星火 链网』超级节点&#…

three.js的demo例子-STL加载对象组件

three.js的demo例子-STL加载对象组件 提示&#xff1a;demo示例中所涉及到的three.js安装插件方法这里就不单个说明了哈&#xff0c;有需要的网上有很多教程 文章目录three.js的demo例子-STL加载对象组件效果展示插件模型一、HTML部分二、script部分1.引入库2.初始化数据3.监听…

卷王都在偷偷准备金三银四了...

年终奖没发&#xff1b; 简历石沉大海&#xff1b; 发消息只读不回 打开某招聘&#xff0c;看了看岗位&#xff0c;这个厂还不错&#xff0c;可是要求好高&#xff0c;我啥都不会。 “哎&#xff0c;算了&#xff0c;我简历还没更新呢&#xff0c;我躺到6月份拿到年终奖再跑…

【动态规划】多重背包问题,分组背包问题

Halo&#xff0c;这里是Ppeua。平时主要更新C语言&#xff0c;C&#xff0c;数据结构算法......感兴趣就关注我吧&#xff01;你定不会失望。 &#x1f308;个人主页&#xff1a;主页链接 &#x1f308;算法专栏&#xff1a;专栏链接 我会一直往里填充内容哒&#xff01; &…

名创优品业绩狂飙,手握哪些王牌?

撰稿 | 多客 来源 | 贝多财经 2023年注定是名创优品(NYSE:MNSO、HKEX:9896)发展史上具有重要意义的一年&#xff0c;不仅是创立的10周年&#xff0c;也是全球品牌战略升级的开局之年。 2月28日&#xff0c;名创优品公布了2023财年第二财季未经审计财务报告。得益于全球化战略…

机器学习笔记之狄利克雷过程(六)预测任务求解

机器学习笔记之狄利克雷过程——预测任务求解引言回顾&#xff1a;基于狄利克雷过程的预测过程预测任务的求解过程引言 上一节引出了基于狄利克雷过程的预测任务&#xff0c;本节将对该预测任务进行求解。 回顾&#xff1a;基于狄利克雷过程的预测过程 在已知隐变量样本集合…

Windows 环境安装Scala详情

为了进一步学习Spark&#xff0c;必须先学习Scala 编程语言。首先开始Scala 环境搭建。温馨提示&#xff1a;本文是基于Windows 11 安装Scala 2.13.1 版本第一步&#xff1a;确保本机已经正确安装JDK1.8 环境第二步&#xff1a;Scala 官网下载我们所属scala版本文件。Scala 官网…

JavaScript(WebAPI)

目录 1.什么是Web API? 2.DOM和DOM树 3.获取元素 4.事件 5.操作元素 获取/修改元素内容 1.innerText 2. innerHTML 获取/修改元素属性 获取/修改表单元素属性 获取/修改样式属性 1.修改内联样式 2.修改元素应用的CSS类名 6.操作节点 新增节点 删除节点 7.案例…

Vue3的composition API—setup函数, ref函数,reactive函数

1、Setup 函数 1.setup 是vue3中的一个配置项 2、setup是所有组件所需要的数据和方法都需要配置到setup中的 3、setup两种返回值&#xff1a; 若返回一个对象 若返回一个渲染函数 mian.js文件 注意&#xff1a;尽量不与Vue2混用 setup中无法访问vue2中的配置 不能是async函数…

Optional--Java8新特性最佳实践

Optional是在 Java8中引入的新特性之一。使用Optional类包装数据&#xff0c;可以避免经典的空检查和一些try-catch代码块。也能够通过链式方法调用&#xff0c;写出更流畅的函数式编程的代码。另一方面&#xff0c;滥用Optional也会导致性能低下和代码混乱。过往项目业务中有大…

【Linux】旋转锁 | 读写锁

在之前的线程学习中&#xff0c;用到的锁都是挂起等待锁&#xff0c;如果申请不到锁&#xff0c;那就会在锁中等待&#xff1b; 自旋锁则不大相似 文章目录1.自旋锁1.1 概念1.2 接口1.2.1 pthread_spin_init/destroy1.2.2 pthread_spin_lock1.2.3 pthread_spin_unlock2.读写锁…

VIO优化中不客观自由度 (gauge freedom) 的处理 (gauge handle)

文章目录1. 不可观的解释2. 几种不同的gauge handle处理方式2.1. free gauge方式2.2. fix gauge方式2.3. prior gauge方式2.4. g2o tutorial方式3.不同方式的协方差矩阵1. 不可观的解释 这篇论文 中对VIO的4-DOF不可观的定义如下&#xff0c;可以看到这种不可观就是如果对最后…