关于new和delete的一些思考,为什么不能在析构函数中调用delete释放对象的内存空间,new和delete的原理

news2025/1/28 1:04:33

  最近在写代码的时候,觉得每次new出来的对象都需要去delete好麻烦,于是直接把delete写到了析构函数中,在析构函数里面写了句delete this,结果调用析构函数的时候死循环了,不是很理解原因,于是去研究了一下。

情景复现

代码

#include <iostream>
#include <string>
using namespace std;
class Book
{
private:
	int id_;
public:
	Book(int id) :id_(id)
	{
	}
	~Book()
	{
		cout << "调用析构函数" << endl;
		delete this;
	}
};
int main()
{
	Book* book1 = new Book(111);
	book1->~Book();
	return 0;
}

结果:死循环然后报错
在这里插入图片描述

new和delete的实现原理

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

(2).对于自定义类型

  • new的原理
    1 调用operator new函数申请空间
    2 在申请的空间上执行构造函数,完成对象的构造
    3 成功的话返回一个指针,失败抛出异常
  • delete的原理
    1 在空间上执行析构函数,完成对象中资源的清理工作
    2 调用operator delete函数释放对象的空间
  • new T[N]的原理
    1 调用operator new[]函数,在operator new[]中实际调用operator new函数完成N个对
    象空间的申请
    2 在申请的空间上执行N次构造函数
    3 成功的话返回一个指针,失败抛出异常
  • delete[]的原理
    1 在释放的对象空间上执行N次析构函数,完成N个对象中资源的清理
    2 调用operator delete[]释放空间,实际在operator delete[]中调用operator delete来释
    放空间

operator new和operator delete的原理

看了下源码

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

  operator new:该函数实际通过malloc来申请空间,当malloc申请空间成功时直接返回;申请空间失败,(尝试执行空间不足应对措施,如果改应对措施用户设置了,则继续申请)否则抛异常。(为什么要封装malloc?为了符合C++里面出问题抛异常这样的一种机制)
  operator delete: 该函数最终是通过free来释放空间的(delete会自动判断指针是否为空指针,如果是空指针则delete不执行任何操作)
  从使用的角度看,和malloc,free没有区别,区别就是operator new delete失败的时候会抛异常。

  因此我们在使用new关键字的时候,可以使用try catch包裹起来对申请空间失败进行处理

try
{
   int *p = new int[10000000000];
}
catch (bad_alloc &e)
{
   cout << e.what() << endl;
   cout << "ok" << endl;
}

重载operator new与operator delete

operator new和operator = 等其他符号一样可以被重载,如果重载了,new的时候就会调用我们重载的那个operator new。
这样有什么好处呢?

  1. 如果我们的类需要频繁调用new,则直接通过new底层的malloc向堆中申请资源,速度就会比较慢,我们可以为当前类实现一个定长的内存池,然后在我们自己的operator new里面不通过malloc申请了,而是通过自己的内存池申请空间,这样就能提高效率。
  2. 如果我们需要在对当前类使用new和delete的时候打印一些日志信息,就可以使用operator new来重载

结论

  delete会先调用对象指针的析构函数,然后再调用国operator delete释放内存,如果没有重载operator delete,默认底层调用的是free。如果在析构函数内部调用delete,delete又会调用析构函数,于是产生死循环。

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

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

相关文章

盘点全球10大女性技术先驱

盘点全球10大女性技术先驱 人们普遍认为技术是男性主导的领域&#xff0c;但事实&#xff0c;技术或编程与性别无关&#xff0c;几乎任何人都可以成为技术大神。已经有很多案例证明女性同样可以在技术领域施展才能。在女神节来临之际&#xff0c;我为大家盘点一下为编程做出卓越…

AB测试——流程介绍(定义问题和指标选取)

前言&#xff1a; 作为AB测试的学习记录&#xff0c;本文主要介绍了AB测试的基本流程&#xff0c;以及指标类型和如何选取合适指标。 相关文章&#xff1a;AB测试——原理介绍 AB测试的基本流程是什么&#xff1f; AB测试&#xff08;也称为分流测试&#xff09;是一种常用的实…

visual studio的team使用问题小结

visual studio的team使用问题小结一、visual studio&#xff08;2017&#xff09;默认浏览器打开team任务和bug二、visual studio&#xff08;2017&#xff09;上传team时&#xff0c;文件超过一万个会上传失败。三、visual studio&#xff08;2017&#xff09;拉取team代码时&…

C++面向对象编程之二:构造函数、拷贝构造函数、析构函数

构造函数和析构函数C利用构造函数和析构函数&#xff0c;完成对象的初始化和清理工作。对象的初始化和清理工作&#xff0c;是编译器强制我们要做的事情&#xff0c;如果我们不提供构造函数和析构函数&#xff0c;编译器会提供3个函数&#xff1a;默认无参构造函数默认拷贝构造…

004+limou+HTML——(4)HTML表格

000、前言 表格在实际开发中的应用还是比较多的&#xff0c;表格可以更加清晰地排列数据 001、基本结构 &#xff08;1&#xff09;构成 表格&#xff1a;<table>行&#xff1a;<tr>&#xff08;table row&#xff0c;表格行&#xff09;&#xff0c;由多少组t…

【每日随笔】中国当前社会阶层 ( 技术无关 | 随便写写 )

文章目录一、阶层划分根据收入划分的阶层根据分工逻辑划分根据权利划分二、根据社会地位和掌握的资源划分的阶层三、赚钱的方式四、如何进入高阶层看了一个有意思的视频 , 讲的是中国当前的社会阶层 , 感觉好有道理 , 搜索了一些资料 ; 参考资料 : 关于中国的社会阶层社会在分…

【一】【socket聊天室】-多线程,socket编程

本文主要实现基于socket编程的聊天室&#xff0c;主要分为下面三个步骤&#xff1a; &#xff08;1&#xff09;多用户聊天&#xff1a;一个服务器多个客户端&#xff0c;客户端信息显示在公共的服务端窗口&#xff0c;利用多线程实现&#xff1b; ——客户端双线程&#xff1a…

OpenCV基础(一)

1.认识图像&#xff08;彩色图中每一个像素点都包含三个颜色通道RGB&#xff0c;数值范围为0~255&#xff0c;0代表黑色&#xff0c;255代表白色&#xff09; import cv2 #opencv 读取的格式为BGRimg cv2.imread(cat.png) #读取图像 cv2.imshow(cat, img) #显示图像img&#x…

Matlab实现FFT变换

Matlab实现FFT变换 文章目录Matlab实现FFT变换原理实现手算验证简单fft变换和频谱求取功率谱结论在信号处理中&#xff0c;快速傅里叶变换&#xff08;FFT&#xff09;是一种非常常见的频域分析方法。本文将介绍如何使用Matlab实现FFT变换&#xff0c;并通过Matlab代码演示实际…

SAP ABAP 深度解析Smartform打印特殊符号等功能

ABAP 开发人员可以在 Smartform 输出上显示 SAP 图标或 SAP 符号。例如,需要在 SAP Smart Forms 文档上显示复选框形状的输出。SAP Smartform 文档上可以轻松显示空复选框、标记复选框以及 SAP 图标等特殊符号。 在 SAP Smartform 文档中添加一个新的文本节点。 1. 单击“更…

开发一款系统软件的流程步骤是什么

在如今的数字化时代&#xff0c;软件开发成为了一个重要的行业。无论是大型企业还是小型创业公司&#xff0c;软件开发都是不可或缺的一环。在本文中&#xff0c;我将介绍一些网上常见的软件开发步骤&#xff0c;以便开发者能够更好地理解和实践。1、需求分析需求分析是开发系统…

基于transformer的多帧自监督深度估计 Multi-Frame Self-Supervised Depth with Transformers

Multi-Frame Self-Supervised Depth with Transformers基于transformer的多帧自监督深度估计0 Abstract 多帧深度估计除了学习基于外观的特征外&#xff0c;也通过特征匹配利用图像之间的几何关系来改善单帧估计。我们采用深度离散的核极抽样来选择匹配像素&#xff0c;并通过一…

基于Jeecgboot前后端分离的ERP系统开发代码生成(六)

商品信息原先生成的不符合要求&#xff0c;重新生成&#xff0c;包括一个附表商品价格信息表 一、采用TAB主题一对多的模式 因为主键&#xff0c;在online表单配置是灰的&#xff0c;所以不能进行外键管理&#xff0c;只能通过下面数据库进行关联录入&#xff0c;否则online界面…

案例19-遇见问题的临时解决方案和最终解决方案

目录1、背景介绍2、两种解决方案的概念1、临时解决方案&#xff1a;2、最终解决方案&#xff1a;3、排查问题过程4、总结站在用户的角度思考作为软件开发者5、升华1、背景介绍 首先说明这是系统很早之前的时候的一个功能&#xff0c;当时和学习通还有很强的耦合关系。在学习通…

研究链表空间销毁问题

&#x1f4af;&#x1f4af;&#x1f4af; 1.研究链表空间销毁问题 当链表使用完后&#xff0c;需要将链表销毁&#xff0c;那么该如何销毁呢&#xff1f; void SLTDestroy(SLTNode* phead)//销毁单链表 {SLTNode* cur phead;while(cur){free(cur);cur cur->next;} }你…

Linux下Nginx安装使用

一、下载解压nginx # 进入要放安装包的目录 cd /opt/software # 下载安装包 wget https://nginx.org/download/nginx-1.20.2.tar.gz # 解压缩 tar -zxvf nginx-1.20.2.tar.gz -C /opt/modules # 进入解压后的目录 cd /opt/modules/nginx-1.20.2/二、安装nginx 1、安装编译器 …

剑指 Offer II 021. 删除链表的倒数第 n 个结点

题目链接 剑指 Offer II 021. 删除链表的倒数第 n 个结点 mid 题目描述 给定一个链表&#xff0c;删除链表的倒数第 n个结点&#xff0c;并且返回链表的头结点。 示例 1&#xff1a; 输入&#xff1a;head [1,2,3,4,5], n 2 输出&#xff1a;[1,2,3,5] 示例 2&#xff1a; …

MySQL的多表操作

多表关系 介绍 实际开发中&#xff0c;一个项目通常需要很多张表才能完成。例如&#xff1a;一个商城项目就需要分类表(category)、商品表(products)、 订单表(orders)等多张表。且这些表的数据之间存在一定的关系&#xff0c;接下来我们将在单表的基础上&#xff0c;一起学习…

DolphinDB 机器学习在物联网行业的应用:实时数据异常率预警

数据异常率预警在工业安全生产中是一项重要工作&#xff0c;对于监控生产过程的稳定性&#xff0c;保障生产数据的有效性&#xff0c;维护生产设备的可靠性具有重要意义。随着大数据技术在生产领域的深入应用&#xff0c;基于机器学习的智能预警已经成为各大生产企业进行生产数…

logback无法删除太久远的日志文件?logback删除日志文件源码分析

logback无法删除太久远的日志文件&#xff1f;logback删除日志文件源码分析 最近发现logback配置滚动日志&#xff0c;但是本地日志文件甚至还有2年前的日志文件&#xff0c;服务器是却是正常的&#xff01; 网上搜索了一波没有发现&#xff0c;只找到说不能删除太久远的旧日志…