关于new和delete的一些思考,为什么不能在析构函数中调用delete释放对象的内存空间,new和delete的原理
最近在写代码的时候,觉得每次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 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:该函数实际通过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。
这样有什么好处呢?
- 如果我们的类需要频繁调用new,则直接通过new底层的malloc向堆中申请资源,速度就会比较慢,我们可以为当前类实现一个定长的内存池,然后在我们自己的operator new里面不通过malloc申请了,而是通过自己的内存池申请空间,这样就能提高效率。
- 如果我们需要在对当前类使用new和delete的时候打印一些日志信息,就可以使用operator new来重载
结论
delete会先调用对象指针的析构函数,然后再调用国operator delete释放内存,如果没有重载operator delete,默认底层调用的是free。如果在析构函数内部调用delete,delete又会调用析构函数,于是产生死循环。
相关文章:
关于new和delete的一些思考,为什么不能在析构函数中调用delete释放对象的内存空间,new和delete的原理
最近在写代码的时候,觉得每次new出来的对象都需要去delete好麻烦,于是直接把delete写到了析构函数中,在析构函数里面写了句delete this,结果调用析构函数的时候死循环了,不是很理解原因,于是去研究了一下。…...
一场以数字技术深度影响和改造传统实业的新风口,正在开启
当数字经济的浪潮开始上演,一场以数字技术深度影响和改造传统实业的新风口,正在开启。对于诸多在互联网时代看似业已走入死胡同的物种来讲,可以说是打开了新的天窗。对于金融科技来讲,同样如此。以往,谈及金融科技&…...
【LeetCode】13. 罗马数字转整数
题目链接:https://leetcode.cn/problems/roman-to-integer/ 📕题目要求: 罗马数字包含以下七种字符: I, V, X, L,C,D 和 M。 例如, 罗马数字 2 写做 II ,即…...
2023/3/8集合之TreeSet HashSet简介 不含代码
TreeSet : 底层是由TreeMap维护的 无序的,不可重的 底层结构 : 红黑树(平衡二叉树) 特点 : 查询效率高,默认升序排序引用场景 : 适合应用在存储多个单个值的数据的集合,去重的,自动升序排序的场景新增方法:新增了一些与比较大小相关的方法 遍历方式 1)foreach 2)iterator 1测试…...
【面试1v1实景模拟】面试中常见的Java关键字详解
笑小枫专属目录老面👴:Java中有哪些关键字老面👴:简单介绍一下 final 关键字老面👴:简单介绍一下 this、super 关键字老面👴:简单介绍一下 static 关键字老面👴ÿ…...
MySQL8.0.16存储过程比5.7.22性能大幅下降
MySQL8.0.16存储过程比5.7.22性能大幅下降 1、背景 从5.7.22迁移数据库到8.0.16,发现存储过程执行性能大幅下降。原来在5版本上执行只需要3-5秒,到8版本上居然要达到上万秒。 5版本: call Calculation_Week() OK 时间: 3.122s 8版本&#x…...
基于MATLAB的无线信道的传播与衰落(附完整代码与分析)
目录 一. 一般路径损耗模型 1. 1自由环境下路径损耗 1. 2 考虑实际情况 1.3 考虑阴影衰落 二. 代码仿真与理解 (1)函数文件 (2)函数文件 (3)主运行文件 三. 运行结果及理解 3.1 3.2 3.3 一. …...
SDX62如何查看Kernel版本和Operating System Version Patch Level
Kernel版本号方法一:adb shell登录,然后执行uname -a# uname -aLinux sdxlemur 5.4.180-perf #1 PREEMPT Fri Mar 3 04:24:42 UTC 2023 armv7l GNU/Linux方法二:内核源码查看,apps_proc/src/kernel/msm-5.4/Makefile 文件…...
001+limou+HTML——(1)HTML入门知识
000、本人编写前言 前言:本笔记来源于莫振杰的书《HTML、CSS、Javascript从零到一快速上手》,经过修改制成的自学笔记,本书很适合小白学习入门web的相关知识,你也可以先看看我从中学到了什么,再考虑是否去认真学习这本…...
使用Arduino Uno构建一个巡线机器人
使用Arduino Uno构建一个巡线机器人 原文 MX 巡线机器人(**LFR)**是一种简单的自主引导机器人,它遵循在地面上绘制的线来检测白色表面上的暗线或黑暗表面上的白线。在本教程中,使用 Arduino Uno 和一些易于访问的组件构建黑线跟…...
【C++】类和对象(收尾)
文章目录成员变量初始化问题初始化列表explicit关键字static成员特性:友元友元函数友元类内部类特性匿名对象成员变量初始化问题 在创建对象时,编译器通过调用构造函数,给了对象中各个成员变量一个合适的初始值。但是这并不能够称为对对象中成…...
Linux延迟操作
一、软中断Linux内核中定义了如下几种软中断:enum {HI_SOFTIRQ0,TIMER_SOFTIRQ,NET_TX_SOFTIRQ,NET_RX_SOFTIRQ,BLOCK_SOFTIRQ,IRQ_POLL_SOFTIRQ,TASKLET_SOFTIRQ,SCHED_SOFTIRQ,HRTIMER_SOFTIRQ,RCU_SOFTIRQ, /* Preferable RCU should always be the last soft…...
np.insert()函数用法
目录insert()函数定义程序举例说明行插入列插入多数值行插入完整的程序和显示结果:insert()函数定义 insert(arr, obj, values, axisNone) 参数说明: arr : 需要插入的数组,即Input array; obj:向数组中插入值的位置…...
学习笔记-架构的演进之容器的封装-3月day06
文章目录前言封装应用的Dockerwhy Docker not LXC?附前言 当文件系统、访问、资源都可以被隔离后,容器就已经具备它降生所需要的全部前置支撑条件了。为了降低普通用户综合使用 namespaces、cgroups 这些低级特性的门槛,2008 年 Linux Kernel 2.6.24 内…...
Gorm根据关系模型中的属性查询原模型数据
type ExamResult struct {gorm.ModelExamManagementID uintExamManagement ExamManagement json:"examManagement" // 一场考试,其中有试卷,有试题,有试题答案//MarkExamPaperRecord MarkExamPaperRecord //每一场考试对应的结…...
车载技术【USB接口】—Android配件协议AOA【AOA连接】
简述 AOA协议是Google公司推出的用于实现Android设备与外围设备之间USB通信的协议。该协议拓展了Android设备USB接口的功能,为基于Android系统的智能设备应用于数据采集和设备控制领域提供了条件。介绍了Android系统下USB通信的两种模式,并给出了USB配件…...
SpringBoot的基本概念和使用
文章目录一、什么是SpringBoot二、Spring Boot优点三、Spring Boot项目创建四、Spring Boot 配置文件1. yml语法2.properties与yml关系3.多系统的配置五、Spring Boot日志文件1.日志对象2.日志级别日志级别的设置System.out.println VS 日志的两个致命缺点3.日志持久化4.更简单…...
基于计算机软件技术的化工设计特点
2.1 便利性将计算机软件技术应用于化工设计环节,最大的优点就在于提升了化工企业生产的便利性。化工设计作为化工生产的基础,在化工设计环节需要到有关化学反应和工艺流程设计等的相关问题,通过利用计算机软件技术可以为上述工作提供很好的辅…...
Nativefier把网页打包成exe
前要: 今天遇到一个需求,之前的应用都是用的h5挂载在企业微信的小应用,但是现在需要电脑运行的exe安装包! 所以需要用到nativefier导报工具:nativefier是一个使用electron将网页转换为app的插件,写这篇博客…...
STM32U5开发(1)----通过 USART1 发送数据
概述 通过 USART1 发送一些数据。 最近在弄ST和GD的课程,需要样片的可以加群申请:6_15061293。 生成例程 使用STM32CUBEMX生成例程,这里使用NUCLEO-U575ZI开发板。 选择工程的时候,先不必选择加载了TrustZone。 样品申请 h…...
【OSG学习笔记】Day 18: 碰撞检测与物理交互
物理引擎(Physics Engine) 物理引擎 是一种通过计算机模拟物理规律(如力学、碰撞、重力、流体动力学等)的软件工具或库。 它的核心目标是在虚拟环境中逼真地模拟物体的运动和交互,广泛应用于 游戏开发、动画制作、虚…...
微软PowerBI考试 PL300-选择 Power BI 模型框架【附练习数据】
微软PowerBI考试 PL300-选择 Power BI 模型框架 20 多年来,Microsoft 持续对企业商业智能 (BI) 进行大量投资。 Azure Analysis Services (AAS) 和 SQL Server Analysis Services (SSAS) 基于无数企业使用的成熟的 BI 数据建模技术。 同样的技术也是 Power BI 数据…...
CMake基础:构建流程详解
目录 1.CMake构建过程的基本流程 2.CMake构建的具体步骤 2.1.创建构建目录 2.2.使用 CMake 生成构建文件 2.3.编译和构建 2.4.清理构建文件 2.5.重新配置和构建 3.跨平台构建示例 4.工具链与交叉编译 5.CMake构建后的项目结构解析 5.1.CMake构建后的目录结构 5.2.构…...
为什么需要建设工程项目管理?工程项目管理有哪些亮点功能?
在建筑行业,项目管理的重要性不言而喻。随着工程规模的扩大、技术复杂度的提升,传统的管理模式已经难以满足现代工程的需求。过去,许多企业依赖手工记录、口头沟通和分散的信息管理,导致效率低下、成本失控、风险频发。例如&#…...
工程地质软件市场:发展现状、趋势与策略建议
一、引言 在工程建设领域,准确把握地质条件是确保项目顺利推进和安全运营的关键。工程地质软件作为处理、分析、模拟和展示工程地质数据的重要工具,正发挥着日益重要的作用。它凭借强大的数据处理能力、三维建模功能、空间分析工具和可视化展示手段&…...
基于数字孪生的水厂可视化平台建设:架构与实践
分享大纲: 1、数字孪生水厂可视化平台建设背景 2、数字孪生水厂可视化平台建设架构 3、数字孪生水厂可视化平台建设成效 近几年,数字孪生水厂的建设开展的如火如荼。作为提升水厂管理效率、优化资源的调度手段,基于数字孪生的水厂可视化平台的…...
2023赣州旅游投资集团
单选题 1.“不登高山,不知天之高也;不临深溪,不知地之厚也。”这句话说明_____。 A、人的意识具有创造性 B、人的认识是独立于实践之外的 C、实践在认识过程中具有决定作用 D、人的一切知识都是从直接经验中获得的 参考答案: C 本题解…...
Netty从入门到进阶(二)
二、Netty入门 1. 概述 1.1 Netty是什么 Netty is an asynchronous event-driven network application framework for rapid development of maintainable high performance protocol servers & clients. Netty是一个异步的、基于事件驱动的网络应用框架,用于…...
深入浅出深度学习基础:从感知机到全连接神经网络的核心原理与应用
文章目录 前言一、感知机 (Perceptron)1.1 基础介绍1.1.1 感知机是什么?1.1.2 感知机的工作原理 1.2 感知机的简单应用:基本逻辑门1.2.1 逻辑与 (Logic AND)1.2.2 逻辑或 (Logic OR)1.2.3 逻辑与非 (Logic NAND) 1.3 感知机的实现1.3.1 简单实现 (基于阈…...
FFmpeg:Windows系统小白安装及其使用
一、安装 1.访问官网 Download FFmpeg 2.点击版本目录 3.选择版本点击安装 注意这里选择的是【release buids】,注意左上角标题 例如我安装在目录 F:\FFmpeg 4.解压 5.添加环境变量 把你解压后的bin目录(即exe所在文件夹)加入系统变量…...
