C++:深入理解operator new/operator delete

动态内存管理

  • 1.语法层面
    • 1.基本语法
      • 注意点
  • 2.new/delete和malloc/free的区别
  • 3.operator new和operator delete函数(底层重点)
    • 1.operator new/delete原理
    • 2.图解
      • 1.new/new[]
      • 2.delete/delete[]
    • 3.new[n]和delete[]
  • 4.定位new
    • 1.定义
    • 2.使用格式

1.语法层面

1.基本语法

class Node
{
public:Node(int val):_val(val),_next(nullptr){}
private:int _val;Node* _next;
};void test()
{int* p1 = new int;                 //申请空间int* p2 = new int(1);              //申请空间 + 初始化int* p3 = new int[4];              //申请4个int整型空间int* p4 = new int[4] {1, 2, 3, 4}; //申请4个整型空间 + 初始化Node* n1 = new Node(2);            //申请空间 + 调用构造函数delete p1;delete p2;delete[] p3;delete[] p4;delete[] n1;
}

在这里插入图片描述

注意点

1.申请单个空间时使用new/delete,申请一段连续空间时使用new[ ]/delete[ ],且一定要匹配使用
2.对于自定义类型,new会调用构造函数,delete会调用其的析构函数

2.new/delete和malloc/free的区别

用法上:

(1)new/delete可以自定义初始化,而malloc/free只负责开空间,不会初始化,且用法上比malloc/free方便

(2)new/delete不需要手动计算申请空间的大小,直接在后面加上类型即可

(3)new/delete不需要强转,malloc和free由于返回值类型为void*,因此需要强转使用

(4)new/delete在实现时使用了抛异常的机制,可以更好的处理问题,而malloc/free则需要手动实现判断

(5)new/delete可以更好的处理自定义类型,对于自定义类型,new的时候调用它的构造函数,delete的时候调用它的析构函数,同时new的时候还可以通过隐式类型转换调用它的有参构造,这对于链表的构造非常方便

(6)new/delete是操作符,malloc和free是函数

3.operator new和operator delete函数(底层重点)

1.operator new/delete原理

在这里插入图片描述

2.图解

1.new/new[]

new/new[]的调用规则如下图。

在这里插入图片描述

2.delete/delete[]

delete/delete[]的调用规则如下图。

在这里插入图片描述

new/delete操作符在二进制指令上本质是调用operator new和operator delete函数,而operator new在底层是对malloc的封装(operator delete)类似。

注意:delete和delete[]必须先调用析构函数,否则对于栈这样的类,它们申请的空间无法释放

在这里插入图片描述

3.new[n]和delete[]

在使用new[n]时,编译器可以通过n确定调用多少次构造函数,但是delete[]时我们并不会给值,那么调用delete[]时编译器如何知道调用多少次析构函数呢。

先看如下代码。

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

按照计算,每一个A中有一个_a,为4个字节,那么申请10个A应该为40字节,可是我们观察汇编,却发现申请了48字节(30为16进制表示),那么多余的8个字节是干什么的呢?

在这里插入图片描述

以下为a的地址,通过内存窗口我们可以看到确实开出了10个整型的空间。

在这里插入图片描述

但是如果再向上看一点,就会发现我们多开出的8个字节。其中存储了十六进制的a(即十进制的10),即为我们需要调用构造函数和析构函数的次数。
在这里插入图片描述

总结:

在我们调用new[]时,会有一个接收的地址,这个地址是我们开辟好的空间的第一个位置的地址,但是编译器其实在这个位置之前多开了字节来存储对象的个数,这样在调用delete[]时就可以通过这个值知道调用多少次析构函数了。如果使用delete[] 来释放空间,那么其在内部会从a指向的空间再向前移动的位置开始释放空间,而不是从a处直接释放空间,如果从a处直接释放空间则会报错。

那么如果不匹配使用,比如:

在这里插入图片描述

此时,由于调用的delete,因此它不会进行指针向前移动字节,而是直接从a的位置开始释放,而申请的空间不能分割释放(也就是释放位置错了),因此会报错。

在这里插入图片描述

上述情况是在我们显式写了析构函数的情况下,==如果我们没有显式写析构函数,那么由编译器默认生成的析构函数没有作用,因此编译器会优化掉,不会调用析构函数,也不会去存储调用次数,不会多申请那一部分空间,==因此不会报错。

从下图可以看到没有多申请空间来存储个数。

在这里插入图片描述

注意:

​ 新版编译器会给出警告如图:

在这里插入图片描述

4.定位new

1.定义

定位new表达式是在已分配的原始内存空间中调用构造函数初始化一个对象。

可以理解为这块空间我先拿到它的使用权,但是我先不初始化使用,等到需要使用的时候再调用定位new。

2.使用格式

new (place_address) type或者new (place_address) type(initializer-list)

注:place_address必须是一个指针,initializer-list是类型的初始化列表

class A
{
public:A(int a = 0): _a(a){cout << "A():" << this << endl;}~A(){cout << "~A():" << this << endl;}
private:int _a;
};

nitializer-list是类型的初始化列表

class A
{
public:A(int a = 0): _a(a){cout << "A():" << this << endl;}~A(){cout << "~A():" << this << endl;}
private:int _a;
};

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

JVM虚拟机(十)Java内存泄漏的排查思路

目录 一、可能产生内存泄露的地方二、复现堆内存泄漏三、如何排查堆内存问题&#xff1f;3.1 获取对内存快照 dump3.2 使用 Visual VM 去分析 dump 文件3.3 定位内存溢出问题 一、可能产生内存泄露的地方 在进行排查 Java 的内存泄漏问题之前&#xff0c;首先我们要知道哪里可…

Vue接收接口返回的mp3格式数据并支持在页面播放音频

一、背景简介 在实际工作中需要开发一个转音频工具&#xff0c;并且能够在平台页面点击播放按钮播放音频 二、相关知识介绍 2.1 JS内置对象Blob Blob对象通常用于处理大量的二进制数据&#xff0c;可以读取/写入/操作文件、音视频等二进制数据流。Blob表示了一段不可变的二…

AI热潮下,公链基础设施赛道都有哪些变化?

最近在一级市场&#xff0c;最火热的赛道无疑是AI&#xff0c;其次是BTC&#xff0c;每天聊的项目80%都集中在这两个赛道&#xff0c;我个人最多的时候一天可以聊5&#xff0c;6个AI项目。 可以预见的是AI泡沫会在明后年达到顶峰&#xff0c;随着数以百计的AI新项目上线&#…

【EI会议征稿通知】2024年图像处理、机器学习与模式识别国际学术会议(IPMLP 2024)

2024年图像处理、机器学习与模式识别国际学术会议&#xff08;IPMLP 2024) 2024 International Conference on Image Processing, Machine Learning and Pattern Recognition 重要信息 大会官网&#xff1a;www.ipmlp.net&#xff08;点击参会/投稿/了解会议详情&#xff09;…

政安晨:【Keras机器学习示例演绎】(一)—— 利用类 U-Net 架构进行图像分割

目录 下载数据 准备输入图像的路径和目标分割掩码 一幅输入图像和相应的分割掩码是什么样子的&#xff1f; 准备数据集&#xff0c;以加载和矢量化成批数据 准备 U-Net Xception 风格模型 预留验证分割 训练模型 可视化预测 政安晨的个人主页&#xff1a;政安晨 欢迎 &…

京东微服务microApp使用总结

前言 基于现有业务门户进行微服务基础平台搭建 主应用框架&#xff1a;vue3vite 子应用框架&#xff1a;vue2webpack / vue3vite在这里插入代码片 本地调试即可&#xff1a;主应用子应用进行打通&#xff08;注意&#xff1a;两者都是vue3vite&#xff09; 问题总结 1.嵌入…

OpenHarmony多媒体-video_trimmer

简介 videotrimmer是在OpenHarmony环境下&#xff0c;提供视频剪辑能力的三方库。 效果展示&#xff1a; 安装教程 ohpm install ohos/videotrimmerOpenHarmony ohpm环境配置等更多内容&#xff0c;请参考 如何安装OpenHarmony ohpm包 。 使用说明 目前支持MP4格式。 视频…

(51单片机)第十一章-串行口应用提高

11.1 方式0应用 在第6章中&#xff0c;已经对51单片机的串行口结构做过详细介绍&#xff0c;并且通过实例讲解了串行口的4种工作方式中方式1的具体用法&#xff0c;本节详细讲述串行口方式0的用法。 串行口方式0被称为同步移位寄存器的输入/输出方式&#xff0c;主要用于扩展并…

Idea修改【Help->Edit Custom VM Options...】后,导致idea无法正常启动的解决方法

一、错误场景: 二、解决方法&#xff1a; 修改文件路径&#xff1a;C:\Users\tianjm&#xff08;写自己的用户名&#xff09;\AppData\Roaming\JetBrains\IdeaIC2024.1&#xff08;选自己安装的版本&#xff09;

【目标检测】Focal Loss

Focal Loss用来解决正负样本不平衡问题&#xff0c;并提升训练过程对困难样本的关注。 在一阶段目标检测算法中&#xff0c;以YOLO v3为例&#xff0c;计算置信度损失&#xff08;图中第3、4项&#xff09;时有目标的点少&#xff0c;无目标的点多&#xff0c;两者可能相差百倍…

视频质量度量VQM算法详细介绍

视频质量评价 视频质量评价(Video Quality Assessment,VQA)是指通过主观、客观的方式对视频图像的内容、画质等,进行感知、衡量与评价。 ITU definations subjective assessment: the determination of the quality or impairment of programme-like pictures presented…

vscode绿绿主题setting config

下载插件Green Tree Theme 选greentree ctrl shift p找到setting {"workbench.colorTheme": "Green Tree","editor.fontSize": 16.5, // 字号"workbench.colorCustomizations": {"[Green Tree]": {"activityBarBadge.…