C++动态内存管理 解剖new/delete详细讲解(operator new,operator delete)

2024-04-17 22:04

本文主要是介绍C++动态内存管理 解剖new/delete详细讲解(operator new,operator delete),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

在这里插入图片描述
讨厌抄我作业和不让我抄作业的人
讨厌插队和不让我插队的人
讨厌用我东西和不让我用东西的人
讨厌借我钱和不借给我钱的人
讨厌开车加塞和不让我加塞的人
讨厌内卷和打扰我内卷的人

一、C++中动态内存管理

1.new和delete操作内置类型

2.new和delete操作自定义类型

二、operator new与operator delete函数

三、operator new[]与operator delete[]函数

四、new和delete的实现原理

五、完结撒❀

–❀–❀–❀–❀–❀–❀–❀–❀–❀–❀–❀–❀–❀–❀–❀-正文开始-❀–❀–❀–❀–❀–❀–❀–❀–❀–❀–❀–❀–❀–❀–❀–

一、C++中动态内存管理

我们在C语言中所学习的动态内存函数:malloc,calloc,ralloc这些在C++中也可以继续进行使用,但是使用起来比较麻烦,并且一些地方留有不足,因此C++又提出了自己的内存管理方式:通过new和delete操作符进行动态内存管理。

再强调一次:new和delete是两个操作符

1.new和delete操作内置类型

操作方式如下:

void Test()
{// 动态申请一个int类型的空间int* ptr1 = new int;// 动态申请一个int类型的空间并初始化为10int* ptr2 = new int(10);// 动态申请10个int类型的空间int* ptr3 = new int[10];//delete完成空间的销毁delete ptr1;delete ptr2;//销毁连续多个空间delete[] ptr3;
}

new和delete对动态内存开辟的操作就是这么朴实无华。

在这里插入图片描述这里注意一下初始化开辟的一个空间数据用(),开辟多个空间内存用[ ],初始化开辟的多个空间类型数据用{},操作如下:

int* ptr0 = new int[10] {1, 2, 3, 4, 5};
delete[] ptr0;

注意:申请和释放单个元素的空间,使用new和delete操作符,申请和释放连续的空间,使用new[]和delete[],注意:匹配起来使用。

2.new和delete操作自定义类型

操作如下:

class A
{
public:A(int a = 0): _a(a){cout << "A():" << this << endl;}~A(){cout << "~A():" << this << endl;}
private:int _a;
};
int main()
{// new/delete 和 malloc/free最大区别是 new/delete对于【自定义类型】除了开空间还会调用构造函数和析构函数A* p1 = (A*)malloc(sizeof(A));A* p2 = new A(1);free(p1);delete p2;// 内置类型是几乎是一样的int* p3 = (int*)malloc(sizeof(int)); // Cint* p4 = new int;free(p3);delete p4;A* p5 = (A*)malloc(sizeof(A) * 10);A* p6 = new A[10];free(p5);delete[] p6;return 0;
}

大家可以运行上面代码,研究观察new和delete与malloc和free的区别。

注意:在申请自定义类型的空间时,new会调用构造函数,delete会调用析构函数,而malloc与free不会。

二、operator new与operator delete函数

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

我们针对代码转到反汇编就可以看到:

在这里插入图片描述
而对于operator new其底层实现是通过malloc函数实现的,operator delete其底层是通过free实现的

见下图:

在这里插入图片描述
在这里插入图片描述这里的_free_dbg表示的就是free,因为free函数是一个宏:

#define   free(p)       _free_dbg(p, _NORMAL_BLOCK)

不仅从汇编我们可以认识operator new函数和operator delete函数,我们还可以看一下其是如何实现的:

/*
operator new:该函数实际通过malloc来申请空间,当malloc申请空间成功时直接返回;申请空间
失败,尝试执行空               间不足应对措施,如果改应对措施用户设置了,则继续申请,否
则抛异常。
*/
void* __CRTDECL operator new(size_t size) _THROW1(_STD bad_alloc)
{// try to allocate size bytesvoid* 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->nBlockUse));_free_dbg(pUserData, pHead->nBlockUse);__FINALLY_munlock(_HEAP_LOCK);  /* release other threads */__END_TRY_FINALLYreturn;
}/*
free的实现
*/
#define   free(p)               _free_dbg(p, _NORMAL_BLOCK)

上面operator new函数和operator delete函数的实现代码大家简单看一下,理解即可,看不懂没有关系

重点是通过上述两个全局函数的实现知道,operator new 实际也是通过malloc来申请空间,如果malloc申请空间成功就直接返回,否则执行用户提供的空间不足应对措施,如果用户提供该措施就继续申请,否则就抛异常。operator delete 最终是通过free来释放空间的

三、operator new[]与operator delete[]函数

我们在开辟多个类型数据时用new T[N],其内部调用的是operator new[]函数,而operator new[]函数其实就是由operator new函数实现完成的,见下面汇编代码:

在这里插入图片描述

在这里插入图片描述
同理delete[]函数内部实现是由operator delete[]函数实现的,而operator delete[]函数内部实现也是由operator delete函数所实现的:

在这里插入图片描述
在这里插入图片描述

operator new[]函数内部实现逻辑由operator new函数实现,那么为什么还需要operator new[]函数呢?

在上面的学习中,我们强调过new和delete配对使用,而new[]要和delete[]进行配对使用,new[]和delete[]是在创建多个类型数据时进行使用,这里对于内置类型来说的话其实没多大意义(因为内置类型不需要调用构造函数和析构函数),主要在自定义类型上面

new和delete在创建和销毁自定义类型分别会自动调用构造函数和析构函数,所以我们在创建多组自定义类型数据时需要根据自定义类型的个数来确定一共需要调用几次构造函数和析构函数

class A
{
public:A(int a = 0):_a(a){cout << "A(int a = 0)" << this << endl;}~A(){cout << "~A()" << this << endl;}
private:int _a;
};int main()
{A* ptr1 = new A; //operator new + 1次构造A* ptr2 = new A[10];//operator new[] + 10次构造delete ptr1;//1次析构 + operator deletedelete[] ptr2;//10次析构 + operator deletereturn 0;
}

而调用operator new[]函数就实现了对类型数据个数的存储,我们可以看下代码:

class A
{
public:A(int a = 0):_a(a){cout << "A(int a = 0)" << this << endl;}~A(){cout << "~A()" << this << endl;}
private:int _a;
};int main()
{A* ptr1 = new A[3];delete[] ptr1;return 0;
}

按照正常计算的话,new开辟A[3]其大小应为12字节,但是我们转到汇编代码:

在这里插入图片描述
会发现一共是16个字节,这里多出来的4个字节就是用来存储总数据个数所用的。

同理,对于operator delete[]函数也一样,operator new[]函数记录了所创建的总数居的多少,也是为下面operator delete[]函数调用多少次析构函数做铺垫。

对于operator delete[]函数,最后也会在内存空间中会向前偏移4个字节的位置再进行free,将所存储数据个数的4个字节一同free掉。

四、new和delete的实现原理

1.内置类型

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

2.自定义类型

· new的原理

1. 调用operator new函数申请空间

2. 在申请的空间上执行构造函数,完成对象的构造

· delete的原理

1. 在空间上执行析构函数,完成对象中资源的清理工作

2. 调用operator delete函数释放对象的空间

· new T[N]的原理

1. 调用operator new[]函数,在operator new[]中实际调用operator new函数完成N个对象空间的申请

2. 在申请的空间上执行N次构造函数

· delete[N]的原理

1. 在释放的对象空间上执行N次析构函数,完成N个对象中资源的清理

2. 调用operator delete[]释放空间,实际在operator delete[]中调用operator delete来释
放空间

通过上面的学习我们可以发现,对于操作符,其内部都是由一条一条指令进行实现的,所以我们使用操作符 ,在编译器编译时就会将操作符转换成每一条指令执行。

五、完结撒❀

如果以上内容对你有帮助不妨点赞支持一下,以后还会分享更多编程知识,我们一起进步。
最后我想讲的是,据说点赞的都能找到漂亮女朋友❤
在这里插入图片描述

这篇关于C++动态内存管理 解剖new/delete详细讲解(operator new,operator delete)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/912976

相关文章

【C++ Primer Plus习题】13.4

大家好,这里是国中之林! ❥前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站。有兴趣的可以点点进去看看← 问题: 解答: main.cpp #include <iostream>#include "port.h"int main() {Port p1;Port p2("Abc", "Bcc", 30);std::cout <<

C++包装器

包装器 在 C++ 中,“包装器”通常指的是一种设计模式或编程技巧,用于封装其他代码或对象,使其更易于使用、管理或扩展。包装器的概念在编程中非常普遍,可以用于函数、类、库等多个方面。下面是几个常见的 “包装器” 类型: 1. 函数包装器 函数包装器用于封装一个或多个函数,使其接口更统一或更便于调用。例如,std::function 是一个通用的函数包装器,它可以存储任意可调用对象(函数、函数

综合安防管理平台LntonAIServer视频监控汇聚抖动检测算法优势

LntonAIServer视频质量诊断功能中的抖动检测是一个专门针对视频稳定性进行分析的功能。抖动通常是指视频帧之间的不必要运动,这种运动可能是由于摄像机的移动、传输中的错误或编解码问题导致的。抖动检测对于确保视频内容的平滑性和观看体验至关重要。 优势 1. 提高图像质量 - 清晰度提升:减少抖动,提高图像的清晰度和细节表现力,使得监控画面更加真实可信。 - 细节增强:在低光条件下,抖

C++11第三弹:lambda表达式 | 新的类功能 | 模板的可变参数

🌈个人主页: 南桥几晴秋 🌈C++专栏: 南桥谈C++ 🌈C语言专栏: C语言学习系列 🌈Linux学习专栏: 南桥谈Linux 🌈数据结构学习专栏: 数据结构杂谈 🌈数据库学习专栏: 南桥谈MySQL 🌈Qt学习专栏: 南桥谈Qt 🌈菜鸡代码练习: 练习随想记录 🌈git学习: 南桥谈Git 🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈�

【C++】_list常用方法解析及模拟实现

相信自己的力量,只要对自己始终保持信心,尽自己最大努力去完成任何事,就算事情最终结果是失败了,努力了也不留遗憾。💓💓💓 目录   ✨说在前面 🍋知识点一:什么是list? •🌰1.list的定义 •🌰2.list的基本特性 •🌰3.常用接口介绍 🍋知识点二:list常用接口 •🌰1.默认成员函数 🔥构造函数(⭐) 🔥析构函数 •🌰2.list对象

06 C++Lambda表达式

lambda表达式的定义 没有显式模版形参的lambda表达式 [捕获] 前属性 (形参列表) 说明符 异常 后属性 尾随类型 约束 {函数体} 有显式模版形参的lambda表达式 [捕获] <模版形参> 模版约束 前属性 (形参列表) 说明符 异常 后属性 尾随类型 约束 {函数体} 含义 捕获:包含零个或者多个捕获符的逗号分隔列表 模板形参:用于泛型lambda提供个模板形参的名

软考系统规划与管理师考试证书含金量高吗?

2024年软考系统规划与管理师考试报名时间节点: 报名时间:2024年上半年软考将于3月中旬陆续开始报名 考试时间:上半年5月25日到28日,下半年11月9日到12日 分数线:所有科目成绩均须达到45分以上(包括45分)方可通过考试 成绩查询:可在“中国计算机技术职业资格网”上查询软考成绩 出成绩时间:预计在11月左右 证书领取时间:一般在考试成绩公布后3~4个月,各地领取时间有所不同

安全管理体系化的智慧油站开源了。

AI视频监控平台简介 AI视频监控平台是一款功能强大且简单易用的实时算法视频监控系统。它的愿景是最底层打通各大芯片厂商相互间的壁垒,省去繁琐重复的适配流程,实现芯片、算法、应用的全流程组合,从而大大减少企业级应用约95%的开发成本。用户只需在界面上进行简单的操作,就可以实现全视频的接入及布控。摄像头管理模块用于多种终端设备、智能设备的接入及管理。平台支持包括摄像头等终端感知设备接入,为整个平台提

6.1.数据结构-c/c++堆详解下篇(堆排序,TopK问题)

上篇:6.1.数据结构-c/c++模拟实现堆上篇(向下,上调整算法,建堆,增删数据)-CSDN博客 本章重点 1.使用堆来完成堆排序 2.使用堆解决TopK问题 目录 一.堆排序 1.1 思路 1.2 代码 1.3 简单测试 二.TopK问题 2.1 思路(求最小): 2.2 C语言代码(手写堆) 2.3 C++代码(使用优先级队列 priority_queue)

计算机毕业设计 大学志愿填报系统 Java+SpringBoot+Vue 前后端分离 文档报告 代码讲解 安装调试

🍊作者:计算机编程-吉哥 🍊简介:专业从事JavaWeb程序开发,微信小程序开发,定制化项目、 源码、代码讲解、文档撰写、ppt制作。做自己喜欢的事,生活就是快乐的。 🍊心愿:点赞 👍 收藏 ⭐评论 📝 🍅 文末获取源码联系 👇🏻 精彩专栏推荐订阅 👇🏻 不然下次找不到哟~Java毕业设计项目~热门选题推荐《1000套》 目录 1.技术选型 2.开发工具 3.功能