「C++」内存管理

news2024/10/7 19:18:02

🎇个人主页:Ice_Sugar_7
🎇所属专栏:C++启航
🎇欢迎点赞收藏加关注哦!

文章目录

  • 🍉内存分布
  • 🍉关键字new
  • 🍉关键字delete
  • 🍉new和delete的封装实现
  • 🍉总结
  • 🍉写在最后

🍉内存分布

C语言阶段我们知道程序内存主要分为五个区域:栈区、堆区、静态区、代码段和内存映射段

①栈区:存储非静态局部变量、函数参数、返回值等。栈是向下增长的(从高地址低地址增长)
②堆区:用于程序运行时动态内存分配(比如malloc动态开辟空间)。堆可以向上增长(从低地址高地址增长)
③静态区:存储全局数据和静态数据(比如static修饰的变量)。静态区是语法层面的概念,后面学习操作系统的时候我们习惯称它为数据段(操作系统层面的概念)
④代码段:存放可执行的代码只读常量
⑤内存映射段:是高效的I/O映射方式,用于装载一个共享的动态内存库。用户可使用系统接口创建共享共享内存(Linux部分学习)

它们分布的示意图如下:
在这里插入图片描述


🍉关键字new

class A {
public:

private:
	int _a;
};

int main() {
	A* p = (A*)malloc(sizeof(A));
	p->_a = 1;
	return 0;
}

上述代码中p->_a = 1;会报错,因为_a是私有成员也就是说malloc不方便处理动态申请的自定义类型对象的初始化问题
C++中的关键字new则可以有效解决这个问题,来看一下如何使用new

	//内置类型
	int* p1 = new int;//动态申请1个整型大小的空间
	int* p2 = new int[5];//动态申请5个整型大小的空间
	int* p3 = new int(5);//动态申请1个整型大小的空间并初始化为5
	
	//自定义类型(假设现在有一个类A)
class A {
public:
	A(int x) {  //构造函数
		_a = x;
	}
private:
	int _a;
};

	A aa1(1);
	A aa2(1);
	A aa3(1);
	A* p4 = new A[3]{ aa1, aa2, aa3 };
	A* p5 = new A[3]{A(2), A(2), A(2) };//匿名对象
	A* p6 = new A[3]{ 3, 3, 3 };//构造+拷贝构造会被编译器优化为直接构造,即此处直接用3构造对象

通过对比,不难看出malloc只开辟空间
而new会做两件事:①开辟一块空间;②进行初始化。比如对于自定义类型,就会调用它的构造函数(没有构造函数那就会报错)
由此可以看出,new和malloc主要的区别还是在自定义类型的动态内存的开辟上,内置类型除了用法不同,没有区别,只不过new比malloc更方便
此外,malloc申请内存失败会返回空指针,而new则会抛出异常,这更符合面向对象的思想


🍉关键字delete

有开辟就有释放,delete对应C语言的free,但是有所改进,delete除了释放空间,如果是自定义类型,那么还会调用析构函数

	double* p1 = new double;
	delete p1;
	
	double* p2 = new double[10];
	delete[] p2;

	//假设有一自定义类型A
	A* p3 = new A[2];
	delete[] p3;  //调用2次析构函数

注意:如果申请多个空间,一定要用delete[],不然结果是未定义的,有可能导致程序崩溃


🍉new和delete的封装实现

C++中newdelete都是操作符,它们在使用时分别会调用全局函数operator newoperator delete
如果是new[ ]和delete[ ]则会分别调用operator new[]operator delete[],但是这两个函数最终也是调用operator newoperator delete

operator new实际上是对malloc进行封装,不过有所改进。对于自定义类型的对象,会调用它的构造函数,失败时抛出异常等(其实就是上面所说的new相较于malloc的优势)

operator delete则是对free进行封装

●接着来说下new T[N],它实际是调用operator new函数完成N个对象空间的申请,也就是调用N次构造函数

●同理,delete[]是调用N次析构函数,然后进行free。中括号里面不用写数字的原因是new T[N]和delete[]是配合使用的,delete[]会自动根据N的大小来决定调用多少次析构函数

调用的途径如下:

new->operator new->malloc
delete->operator delete->free

new:先调用operator new申请空间,然后如果是自定义类型,则会调用构造函数
delete:先调用析构函数(自定义类型),然后再调用operator delete释放空间


🍉总结

最后总结一下malloc&free和new&delete的区别(面试题常考)

①malloc和free是函数,new和delete是操作符
②malloc申请的空间不会进行初始化,而new对于自定义类型会调用它的构造函数
③malloc申请空间时,需要我们手动计算所需空间的大小;而new只需写多少个所需类型大小的空间
④malloc返回值类型是void*,接收返回值需要强制类型转换;而new不用
⑤malloc申请空间失败的话,会返回空指针NULL,我们需要判断是否为空;而new不需要,但它需要捕获异常
⑥申请自定义类型对象时,malloc/free只会开辟空间,不会调用构造函数与析构函数;而new在申请空间后会调用构造函数完成对象的初始化,delete在释放空间前会调用析构函数完成空间中资源的清理


🍉写在最后

以上就是本篇文章的全部内容,如果你觉得本文对你有所帮助的话,那不妨点个小小的赞哦!(比心)

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

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

相关文章

kafka 详细介绍

目录 前言 分布式架构: 消息发布-订阅模型: 持久性存储: 分区和副本: 水平扩展: 高性能: 生态系统: 我的其他博客 前言 Kafka 是由 Apache 软件基金会开发的一种开源流处理平台&#xf…

基于Java SSM框架实现沙县小吃门店连锁点餐订餐系统项目【项目源码+论文说明】

基于java的SSM框架实现县小吃门店连锁点餐订餐系统演示 摘要 随着社会的发展,社会的各行各业都在利用信息化时代的优势。计算机的优势和普及使得各种信息系统的开发成为必需。 沙县小吃点餐系统,主要的模块包括实现管理员;个人中心、用户管…

视频推拉流平台EasyDSS点播文件播放请求添加token验证的实现方法

EasyDSS视频直播点播平台可提供一站式的视频推拉流、转码、点播、直播、播放H.265编码视频等服务,搭配RTMP高清摄像头使用,可将设备的实时流推送到平台上,实现无人机视频推流直播等应用。今天我们来介绍下EasyDSS系统点播文件播放请求添加tok…

实战章节:在Linux上部署各类软件

详细资料见文章的资源绑定 一、前言 1.1 为什么学习各类软件在Linux上的部署 在前面,我们学习了许多的Linux命令和高级技巧,这些知识点比较零散,同学们跟随着课程的内容进行练习虽然可以基础掌握这些命令和技巧的使用,但是并没…

TDengine Kafka Connector将 Kafka 中指定 topic 的数据(批量或实时)同步到 TDengine

教程放在这里:TDengine Java Connector,官方文档已经写的很清晰了,不再赘述。 这里记录一下踩坑: 1.报错 java.lang.UnsatisfiedLinkError: no taos in java.library.pathat java.lang.ClassLoader.loadLibrary(ClassLoader.j…

【Geoserver】将geoserver迁移到jetty的发行包中

之前讲了在Geosever的二进制发行包中升级jetty的内容,我测试之后发现有些问题,本地运行可能没有问题,但是在linux上运行报错了。 于是我想着换个思路好了,总是想着将Geosever中的jetty包替换掉,干脆反过来,…

Java 数据结构篇-用数组、堆实现优先级队列

🔥博客主页: 【小扳_-CSDN博客】 ❤感谢大家点赞👍收藏⭐评论✍ 文章目录 1.0 优先级队列说明 2.0 用数组实现优先级队列 3.0 无序数组实现优先级队列 3.1 无序数组实现优先级队列 - 入队列 offer(E value) 3.2 无序数组实现优先级队列 - 出…

mysql数据备份策略-shell脚本优化代码

一.备份的主机上需要自己手动安装xtrabackup工具 1.安装xtrabackup-yum源 #下载xtrabackup的yum源 wget http://www.percona.com/downloads/percona-release/redhat/0.1-4/percona-release-0.1-4.noarch.rpmrpm -ivh percona-release-0.1-4.noarch.rpm2.打开yum源 #打开xtra…

竞赛保研 python 机器视觉 车牌识别 - opencv 深度学习 机器学习

1 前言 🔥 优质竞赛项目系列,今天要分享的是 🚩 基于python 机器视觉 的车牌识别系统 🥇学长这里给一个题目综合评分(每项满分5分) 难度系数:3分工作量:3分创新点:3分 🧿 更多资…

道路坑洞数据集(坑洞目标检测)VOC+YOLO格式650张

路面坑洞的形成原因是由于设计、施工、养护处理不当、控制不适和受气候、环境、地质、水文等自然因素影响,以及车辆的运行和车辆超载运行导致路面破损,出现坑洞的现象。 路面坑洞的分类: (1)路面混凝土板中坑洞&…

你真的了解进程注入吗?

关注公众号回复20231110获取最新网络安全以及内网渗透等资料。 文章目录 关注公众号回复20231110获取最新网络安全以及内网渗透等资料。进程注入进程注入是什么?windows进程虚拟地址空间句柄Tokens线程数特权shellcode注入 进程注入 进程注入是什么? 攻…

Python码上行动系列丛书(由北京大学出版社出版)

前言 Python码上行动系列丛书火热来袭💥💥💥 三册在手,Python全掌握!无论是初学者还是进阶玩家,我们都有你想要的! 让ChatGPT带你轻松入门Python编程,享受编程带来的乐趣&#xff0…

git 实用命令杂记

使用解决冲突的方式合并,将避免简单的自动合并 git merge origin/dev --strategyresolve清理本地已经合并到 dev 的分支 git branch --merged | grep -v dev | xargs -n 1 git branch -d分支清理 Git 之删除本地无用分支_dearfulan 的博客 - CSDN 博客_git 删除本…

RV32/64 特权架构

machine mode: 运行最可信的代码;supervisor mode:为 Linux,FreeBSD 和 Windows 等操作系统提供支持;user mode:权限最低,应用程序的代码在此模式下运行; 这两种新模式都比user mode有着更高的权限,有更多权限的模式通常可以使用…

C/C++ 快乐数: 编写一个算法来判断一个数n是不是快乐数

题目: 编写一个算法来判断一个数n是不是快乐数。 快乐数的定义: 对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和。 然后重复这个过程直到这个数变为 1,也可能是 无限循环 但始终变不到 1。 如果这个过…

数字中台建设指南(大数据平台)

制定数字中台战略规划:制定符合企业实际情况的数字中台战略规划,明确建设目标、重点任务和时间表。确定数字中台架构:根据企业业务需求和特点,确定数字中台的架构,包括技术架构、应用架构和数据架构。搭建数字中台基础…

制作Windows 11的U盘启动工具的两种方法,以及如何使用它来安装

本文介绍了如何创建Windows 11的U盘启动工具,以及如何使用它来安装Windows 11。 Windows 11 Media Creation Tool 微软网站上提供的Windows 11 Media Creation Tool可以帮助你创建Windows 11的U盘启动工具。它真的很容易使用,因为它可以引导你完成所有的步骤。 1、访问Mic…

接口测试要测试什么?怎么测?

本文主要分为两个部分: 第一部分:主要从问题出发,引入接口测试的相关内容并与前端测试进行简单对比,总结两者之前的区别与联系 第二部分:主要介绍为什么要做接口测试,并简单总结接口持续集成和接口质量评估…

textarea 网页文本框在光标处添加内容

在前端研发中我们经常需要使用脚本在文本框中插入内容。如果产品要求不能直接插入开始或者尾部,而是要插入到光标位置,此时我们就需要获取光标/光标选中的位置。 很多时候,我在格式化文本处需要选择选项,将选择的信息输入到光标位…

Nginx【通俗易懂】《中篇》

目录 1.Url重写rewrite 2.防盗链 3.静态资源压缩 4.跨域问题 1.Url重写rewrite 🤩🤩🤩 1.1.rewrite书写格式 rewrite是实现URL重写的关键指令,根据regex(正则表达式)部分内容,重定向到rep…