C++4:C++中的动态内存管理

news2024/12/26 9:29:29

目录

C++内存管理方式

 new/delete操作内置类型:

 new/delete操作自定义类型:

new和delete的底层实现:

operator new与operator delete函数

定位new

内存泄漏

动态内存管理,早些我们接触C语言的时候就已经在很熟练的游玩在堆上开空间的操作了,我们最开始的应用莫过于数据结构顺序表的实现,其中的扩容我们已经再熟悉不过了

//扩容
    if (slt->size == slt->capacity)
    {
        int newcapacity = slt->capacity == 0 ? 4 : slt->capacity * 2;
        Datatype* tmp = (Datatype*)realloc(slt->a, newcapacity * sizeof(Datatype));
        if (realloc == NULL)
        {
            perror("realloc fail!");
            exit(-1);
        }

        slt->a = tmp;
        slt->capacity = newcapacity;
    }

但是我们总是绕不开开辟完毕的返回值需要判空的问题

那么C++作为C的升级,在动态内存管理上是否有什么讨喜的升级呢?

C++内存管理方式

 new/delete操作内置类型

C++中开辟内存空间的关键字升级成了new,相较于C语言较为繁琐的申请格式,new则简单粗暴的多,其释放也非常简单。

有如下三种使用new的方式

void Test()
{
    // 动态申请一个int类型的空间
    int* ptr4 = new int;

    // 动态申请一个int类型的空间并初始化为10
    int* ptr5 = new int(10);

    // 动态申请10个int类型的空间
    int* ptr6 = new int[3];

    delete ptr4;
    delete ptr5;
    delete[] ptr6;
}

 new和delete的格式一定要对齐,也就是如果使用了new[]就必须对应着使用delete[]


 new/delete操作自定义类型

对于自定义类型,new会直接调用其构造函数,delete会调用其析构函数,而malloc和free则不会。

malloc过大的空间的时候会直接崩溃,而new则是抛异常,由于牵扯到多态和继承的问题,不记述。

示例: 


new和delete的底层实现:

new和delete是用户进行动态内存申请和释放的操作符,operator new 和operator delete是系统提供的全局函数,new在底层调用operator new全局函数来申请空间,delete在底层通过operator delete全局函数来释放空间。

既然new是调用operator函数来实现的,那么这个全局函数又是怎么实现的?


operator new与operator delete函数

我们来看看原码

void* __CRTDECL operator new(size_t size) _THROW1(_STD bad_alloc)
{
	// try to allocate size bytes
	void* p;
	while ((p = malloc(size)) == 0)
		if (_callnewh(size) == 0)
		{
			// report no memory
			// 如果申请内存失败了,这里会抛出bad_alloc 类型
			static const std::bad_alloc nomem;
			_RAISE(nomem);
		}
	return (p);
}
/*
operator delete: 该函数最终是通过free来释放空间的
*/
void operator delete(void* pUserData)
{
	_CrtMemBlockHeader* pHead;
	RTCCALLBACK(_RTC_Free_hook, (pUserData, 0));
	if (pUserData == NULL)
		return;
	_mlock(_HEAP_LOCK); /* block other threads *
	__TRY

	/* get a pointer to memory block header *
	pHead = pHdr(pUserData);
	/* verify block type */
	_ASSERTE(_BLOCK_TYPE_IS_VALID(pHead->nBlo
		_free_dbg(pUserData, pHead->nBlockUse);
	__FINALLY
		_munlock(_HEAP_LOCK); 
		__END_TRY_FINALLY
		return;
	}

原码虽然看上去很复杂,但是我们也能在里面找到一些老熟人,比如malloc和free,这下我们知道了,new和delete的底层实现也是依靠于malloc和free实现。

那么问题来了,C++弄这么大一坨封装malloc的意义在哪?

答:封装malloc的意义则是申请内存失败就抛异常

那么总结一下new对内置类型和自定义类型的实现原理

对于内置类型:

如果申请的是内置类型的空间,new和malloc,delete和free基本类似,不同的地方是:
new/delete申请和释放的是单个元素的空间,new[]和delete[]申请的是连续空间,而且new在申请空间失败时会抛异常,malloc会返回NULL。

对于自定义类型:

new的原理
1. 调用operator new函数申请空间
2. 在申请的空间上执行构造函数,完成对象的构造

delete的原理
1. 在空间上执行析构函数,完成对象中资源的清理工作
2. 调用operator delete函数释放对象的空间

new T[N]的原理
1. 调用operator new[]函数,在operator new[]中实际调用operator new函数完成N个对象空间的申请
2. 在申请的空间上执行N次构造函数

delete[]的原理
1. 在释放的对象空间上执行N次析构函数,完成N个对象中资源的清理
2. 调用operator delete[]释放空间,实际在operator delete[]中调用operator delete来释放空间


定位new

定位new可以直接调用某一个类里的构造函数,但是它需要一个地址以及其对象的类。

那么如何销毁这块空间呢?

析构函数可以显式调用,可以直接调。

直接delet这块空间也是可以的,因为delete的底层依旧是free和调用析构函数,本质上和上面两段代码没有本质区别

当然以上的开辟方法其实还是完全不敌new。


内存泄漏

内存泄漏的本质我个人更加愿意理解为空间的遗忘,内存泄漏并不是指内存在物理上的消失,而是应用程序分配某段内存后,因为设计错误,失去了对该段内存的控制,因而造成了内存的浪费。
虽然说对正常结束的程序影响不大,但是对长期运行的程序就是定时炸弹。被遗忘的空间会越来越大,最终导致占用过多的内存导致程序崩溃

如何避免内存泄漏
1. 工程前期良好的设计规范,养成良好的编码规范,申请的内存空间记着匹配的去释放。ps:
这个理想状态。但是如果碰上异常时,就算注意释放了,还是可能会出问题。需要下一条智
能指针来管理才有保证。
2. 采用RAII思想或者智能指针来管理资源。
3. 有些公司内部规范使用内部实现的私有内存管理库。这套库自带内存泄漏检测的功能选项。
4. 出问题了使用内存泄漏工具检测。ps:不过很多工具都不够靠谱,或者收费昂贵
 


以上就是C++中的动态内存管理的概述了!希望对你有点帮助!感谢阅读!

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

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

相关文章

QGIS加载谷歌地图(google map)方法

目录第一步第二步将Google提供的网络地图,包括地图和卫星影像等,作为图层加载到QGIS中,有时可辅助地学分析。QGIS已经提供了OpenStreetMap,在 “XYZ Tiles” 里面加载即可。 谷歌街道地图:http://mt2.google.com/vt/ly…

缓冲区的深刻理解

代码&&现象 先来看一份代码 #include <stdio.h> #include <string.h> #include <unistd.h> int main() {//C Libraryprintf("hello printf\n");fprintf(stdout, "hello fprintf\n");const char *s1 "hello fwrite\n&quo…

微信公众号开发以及测试公众号菜单配置

微信公众号开发测试号申请测试号配置公众号菜单配置1、获取access_token2、新增自定义菜单微信扫描关注公众号微信公众平台测试号申请 1、测试号申请 开发的时候需要一个个人的公众号调试&#xff0c;所以使用微信测试号进行。 1、微信测试号申请地址: https://mp.weixin.qq.c…

用于野外精确人体姿态估计的自适应多视图融合

用于野外精确人体姿态估计的自适应多视图融合 Abstract AdaFuse&#xff1a;一种自适应的多视图融合方法&#xff0c;利用可见视图中的特征增强被遮挡视图中的特征核心&#xff1a;确定两个视图之间的点-点对应关系 通过研究热图表示的稀疏性 我们还学习了一个自适应的融合…

ArcGIS基础实验操作100例--实验48按分区划分矢量图层

本实验专栏参考自汤国安教授《地理信息系统基础实验操作100例》一书 实验平台&#xff1a;ArcGIS 10.6 实验数据&#xff1a;请访问实验1&#xff08;传送门&#xff09; 高级编辑篇--实验48 按分区划分矢量图层 目录 一、实验背景 二、实验数据 三、实验步骤 &#xff08;…

属于 PingCAP 用户和开发者的 2022 年度记忆

2022 年&#xff0c;我们一起穿越了许多荆棘时刻&#xff0c;面对着前所未有的不确定性。在这些挑战面前&#xff0c;我们发现技术和开发者扮演了重要角色。 技术为我们提供了穿越周期的桥梁&#xff0c;开发者帮助我们更好地应对挑战&#xff0c;解决问题并赋予这个世界更多创…

Qt——项目:翻转金币游戏

目录 一.示例演示 二.制作思路 &#xff08;一&#xff09;.准备资源及总体框架 &#xff08;二&#xff09;.开始窗口 &#xff08;三&#xff09;.选择关卡窗口 &#xff08;四&#xff09;.游戏窗口 &#xff08;五&#xff09;.优化 三.实现代码 &#xff08;一&a…

电脑系统格式化需不需要重装系统

​有小伙伴反应系统中毒无法彻底杀毒&#xff0c;不知道格式化需不需要重装系统吗那么下面小编给大家说说并且带来格式化重装系统步骤图解。 工具/原料&#xff1a; 系统版本&#xff1a;windows10系统 品牌型号&#xff1a;惠普战66五代 软件版本&#xff1a; 方法/步骤&…

【LeetCode】1802. 有界数组中指定下标处的最大值

1802. 有界数组中指定下标处的最大值 题目描述 给你三个正整数 n、index 和 maxSum 。你需要构造一个同时满足下述所有条件的数组 nums&#xff08;下标 从 0 开始 计数&#xff09;&#xff1a; nums.length nnums[i] 是 正整数 &#xff0c;其中 0 < i < nabs(nums…

怎么做form表单校验

这里写自定义目录标题欢迎使用Markdown编辑器新的改变功能快捷键合理的创建标题&#xff0c;有助于目录的生成如何改变文本的样式表单校验1、input框生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants创建一个自定义列表如何创建一个注脚注释也是必不可少的…

小程序从启动到发版

记录一下从拿到项目启动到发版的流程。 每个uniapp项目&#xff0c;管理员都会给你下发权限&#xff0c;用微信扫一扫登录 小程序官网 你可以在手机上看到你所有的权限账号&#xff0c;选择当前项目登录&#xff08;没有就是没下发你权限&#xff0c;找他去&#xff09; 开…

知道了这些vim编辑器使用小技巧可以让你写代码的速度直接飞起

文章目录一、前言二、Vim 编辑器的简单介绍2.1 命令模式2.2 输入模式2.3 底部命令模式2.4 三种模式的切换三、Vim 编辑器常用操作3.1 Vim 最基本的操作3.2 Vim 的光标移动操作3.3 多窗口同时打开多个文件四、一些其他的 Vim 小技巧一、前言 相信学习过Linux的朋友们对于Vim编辑…

pmp证书含金量怎么样?

含金量的问题&#xff0c;其实经过了这一系列的学习&#xff0c;这个证书对于学员们来说&#xff0c;只是一个证明自己有这个能力的证件而已&#xff0c;就算没有这个证件&#xff0c;他所学习的知识就不在自己的脑中了吗&#xff1f;必然是不可能的&#xff01; 这其实就是一…

excel函数应用:如何用数位函数分段提取身份证信息 下篇

在上篇内容中我们说到了用excel提取身份证号码中的户籍地址、出生日期、年龄、生肖、星座等内容&#xff0c;今天我们书接上回&#xff0c;继续带大家学习excel提取身份证信息的其他操作&#xff01;4、生日提醒生日提醒的问题&#xff0c;作者觉得要分两部分来说。&#xff08…

Reids的BigKey和HotKey

1.什么是BigKey和HotKey 1.1.Big Key Redis big key problem&#xff0c;实际上不是大Key问题&#xff0c;而是Key对应的value过大&#xff0c;因此严格来说是Big Value问题&#xff0c;Redis value is too large (key value is too large)。 到底多大的value会导致big key问…

各行业执法图传系统建设建议(华脉智联内参二)

各行业执法图传系统建设建议 让执法透明&#xff0c;不断提高执法工作效能 题记&#xff1a;为实现执法过程中的证据固定与执法场景记录&#xff0c;采用照相机、录音笔或固定监控等传统手段进行取证一直是最本源的需求。随着时代的变迁&#xff0c;传统的手段取证已无法满足完…

知识图谱构建:py2neo案例100个知识点应用

连接到 Neo4j 数据库执行一条简单的 Cypher 查询从查询结果中提取节点和关系插入一个新节点并与另一个节点建立关系根据标签查找节点根据属性查找节点根据关系查找节点在事务中执行多条查询使用索引查找节点使用约束确保唯一性删除节点和关系使用 py2neo.ogm 在 Python 中创建对…

访问学者申请要求及各国情况

访问学者申请要求及各国情况&#xff0c;下面就随知识人网小编一起来看一看。一、访问学者申请要求1、自身条件&#xff1a;访问学者主要是参看申请人当前的工作背景&#xff0c;专业背景以及科研背景等。在职群体申请访学需要具备本科学历和学位。此外&#xff0c;最重要的就是…

2023年,开挖电商这座金矿,有飞项这个协同工具就够了

2023年电商潜力怎样&#xff1f;据Morgan Stanley 研究&#xff0c;全球电商渗透还未见顶&#xff0c;物流发展、移动设备普及和市场拓展等因素仍然有利于电商发展&#xff0c;长期来看仍有增长空间&#xff0c;当前3.3万亿美元的电商市场规模有望在2026年增长到5.4万亿。 如何…

测试的准入准出

测试的准入准出 测试的准入住处是指什么情况下可以开始当前版本的测试工作&#xff0c;什么情况下可以结束当前版本的测试工作。不同项目、不同公司的测试准入准出标准都会有所不同。下面介绍一些通用的测试准入准出标准。 测试准入标准如下&#xff1a; (1)开发编码结束&#…