C++——new和delete关键字

news2025/1/20 14:48:40

什么是new和delete

newdelete不是函数,和sizeof一样都是C++定义的关键字,不同的是sizeof在编译时就可以确定其返回值,而newdelete相对复杂

示例

string *ps = new string("hello world");

如果换做c语言,上面这句话就会变成:

char *ps = (char *)malloc(sizeof(char)*12);
ps = "hello world";

这里就可以看出newmallocc的几点不同:

  • malloc申请完空间后不会对内存进行必要的初始化,而new 可以
  • new操作符内存分配成功时,返回的是对象类型的指针,类型严格与对象匹配,无须进行类型转换,即new类型安全性的操作符;而malloc内存分配成功后返回的是void*,需要通过强制类型转换,将通用类型指针void*转换成所需要的指针
  • new操作符申请内存分配时无须指定内存块的大小,编译器会根据类型信息自行计算;而malloc需要显示地写出所需内存块的大小

new和malloc更多的不同请参考此文章

总结表

特征new/deletemalloc/free
分配内存的位置自由存储区
内存分配成功的返回值完整类型指针void*
内存分配失败的返回值默认抛出异常返回NULL
分配内存的大小由编译器根据类型计算得出必须显式指定字节数
处理数组有处理数组的new版本new[]需要用户计算数组的大小后进行内存分配
已分配内存的扩充无法直观地处理使用realloc简单完成
是否相互调用可以,看具体的operator new/delete实现不可调用new
分配内存时内存不足客户能够指定处理函数或重新制定分配器无法通过用户代码进行处理
函数重载允许不允许
构造函数与析构函数调用不调用

new和delete的背后机制

通过示例说明:

class A
{
  private:
    int var;
    FILE *file;
   public:
   	A(int v): var(v) {
        fopen_s(&file, "test", "r");
    }
    ~A(){
        fclose(file);
    }
};

类A中有两个私有成员,一个构造函数和析构函数,构造函数根据传递参数初始化var并且打开文件,析构函数关闭文件

我们使用下面代码创建一个类的对象,返回其指针pa

A *pa = new A(10);

如下图所示new完成的工作:

在这里插入图片描述

可以将new实例化对象的过程分为三步:

  1. 分配指定大小的内存块;
  2. 在内存块上调用构造函数对类对象进行初始化
  3. 返回内存块的地址(指针)

那么delete会做什么呢?

delete pa;

如下图所示:

即将delete一个对象的过程也可以分两步:

  1. 先调用析构函数,将打开的文件关闭
  2. 释放pa所指内存块的空间,即pa变成空指针

申请和释放一个数组

常用的动态分配一个数组方法

string *psa = new string[10];
int *pia = new int[10];

上面在申请数组的时候都用到了new []表达式,第一个数组是string类型,在分配了保存对象的内存空间(10个string的大小),并调用string类的默认构造函数来依次初始化每个元素,最后返回第一个string的地址作为string数组的地址;第二个数组是int类型的,int是内置类型不存在构造函数,所以new的过程中,不存在初始化,只分配了10个int类型的内存空间。

如果想释放空间,则使用下面语句

delete [] psa;
delete [] pia;

都用到了delete []表达式,注意这个[]一般情况下不能漏下。释放string数组的空间时,先对数组内的每个元素都调用析构函数析构对象,再释放掉整个数组的空间;而在释放int数组时,因为不存在析构函数,所以会直接释放整个int数组的空间。

可以看到delete[]中并没有填数组的大小,那么delete关键字怎么知道需要调用析构函数多少次呢?

回到new [size],我们new一个对象数组时,还需要保存数组的维度,c++的做法是在分配数组空间时多分配4个字节,专门保存数组的大小,在delete []时就可以取出这个保存的数,就知道需要调用析构函数多少次了。

依旧以类A为例,

A *pAa = new A[3];

发生过程如下图:

在这里插入图片描述

注意到,在申请数组对象的上面确实多分配了4个字节用来保存数组的大小,但是最终返回的地址(指针)是指向第一个数组元素的。

在释放空间时:

delete []pAa;

发生的过程如下图:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Oq1fz5ju-1669642247943)(D:\Note\截图\image-20221128211757009.png)]

要注意的是,先从目标地址的前4个字节中,取出数作为调用析构函数的次数,依次析构数组内的元素;最后在释放内存空间的时候,传递给operator delete[]()的参数是pAa-4,即还要释放前面4个字节

new/delete与new[]/delete[]的配对使用

经过上面的分别对new/delete和new[]/delete[]的使用,可以得知这两对之间一般情况下不能拆开随意组合,不然会导致严重的内存泄露/重复释放问题

string *psa = new string[10];
delete psa;

如果delete没有后面的[]意味它只会析构一次,那么剩下的9个string对象和上面的4字节数将永远不会被释放,当数组很大时会造成很严重的内存泄露;相反如果是new/delete[]会导致重复释放内存的问题。

一般情况下意味也有特殊情况,如下所示:

int *pia = new int[10];
delete pia;

这个操作又是合理的,因为差别在int和string不同,int是内置类型,不存在构造和析构函数,也就是说new[]的时候多分配的4个字节,是因为delete的时候需要知道调用析构函数的次数,但是当对象类型都没有析构函数时,也就没有多分配这4个字节的必要。直接delete piaoperator delete传递的参数就是pia的值(数组第一个元素的地址),直接释放所分配的内存块大小即可,无需析构。

参考文章
浅谈 C++ 中的 new/delete 和 new[]/delete[]

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

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

相关文章

数据库——数据库备份与恢复

目录 原因: 数据库的备份与恢复: 1、使用MySQLdump命令备份 2、恢复数据库 表的导入和导出 1、表的导出 2、表的导入 原因: 尽管采取了一些管理措施来保证数据库的安全,但是不确定的意外情况总是有可能造成数据的损失,…

数据库理论 05 关系数据库设计——基于《数据库系统概念》第七版

通过E-R图转换得出一组关系模式后 **选择1:**把一些关系模式合并为更大的关系 —— 会产生过多的数据冗余 inst_dept(ID, name, salary, dept_name, building, budget)如果通过E-R模型转换得出如下两个关系模式 sec_class(sec_id, building, room_number) and se…

2023最新SSM计算机毕业设计选题大全(附源码+LW)之java计算机专业建设管理系统3286d

面对老师五花八门的设计要求,首先自己要明确好自己的题目方向,并且与老师多多沟通,用什么编程语言,使用到什么数据库,确定好了,在开始着手毕业设计。 1:选择课题的第一选择就是尽量选择指导老师…

ThreadLocal源码解析 1.运行原理

ThreadLocal源码解析—运行原理 简介 ThreadLocal 类用来提供线程内部的局部变量,这种变量在多线程环境下访问(通过 get 和 set 方法访问)时能保证各个线程的变量相对独立于其他线程内的变量,分配在堆内的 TLAB 中。 ThreadLoc…

【Mybatis编程:根据若干个id批量删除相册(动态SQL)】

目录 1. 执行的SQL语句 2. 在AlbumMapper.java接口添加抽象方法 3. 在AlbumMapper.xml中配置以上抽象方法映射的SQL语句 4. 标签书写规范 1. 执行的SQL语句 需要执行的SQL语句大致是: delete from pms_album where id? or id? or ... id? delete from pms…

《机器学习实战》10.K-均值聚类算法

目录 利用K-均值聚类算法对未标注数据分组 K-均值聚类算法 2 使用后处理来提高聚类性能 3 二分K-均值算法 4 示例:对地图上的点进行聚类 4.1 Yahoo!PlaceFinder API 4.2 对地理坐标进行聚类 5 本章小结 本章涉及到的相关代码和数据 利用K-均值聚…

Unity基本编译环境设置(代码自动补全)

基本说明: 中国 Unity 官网下载地址:https://unity.cn/releases 请下载 Unity HUB 来管理和安装你的 Unity 各种版本 场景一: Windows系统 |Unity 2020之前的版本 |Visual Studio Community编辑器 电脑中没有任何…

并发控制常用定位方法及解决措施

并发控制常用定位方法及解决措施 7.1 排队问题 出现业务阻塞、性能下降、查询无响应等类似现网问题时,通过以下方法可以排查是否排队问题并定位排队原因,同时根据排队原因给出相应规避措施。 7.1.1 确认是否排队 首先确认是否排队问题,其…

力扣(LeetCode)2095. 删除链表的中间节点(C++)

快慢指针 设置哑结点,便于删除头结点。找到链表的中间结点,可以用快慢指针从头结点出发,慢指针最后停在中间结点。删除中间结点,应当找中间结点的前一个结点。于是想到加入哑结点,这样初始快慢指针既可以往前一个位置…

RADServer应用程序的交钥匙应用程序基础

RADServer应用程序的交钥匙应用程序基础 RADServer是快速构建和部署基于服务的应用程序的交钥匙应用程序基础。RAD Server提供自动化的Delphi和CREST/JSON API发布和管理、企业数据库集成中间件、IoT Edgeware和一系列应用程序服务,如用户目录和身份验证服务、推送通…

retimer芯片调式总结

1,主备状态是否ok。 看里面的0-3工作在Master(master Active), 4-7 工作在Master(wait master),主控0-3,备控4-7. current postion说明: typedef enum {VEGA_HMUX_SWITCH_TO_MASTER = 0,VEGA_HMUX_SWITCH_TO_SLAVE = 1,VEGA_HMUX_SWITCH_TO_PATTERN = 2,VEGA_HMUX_SWITC…

VSCode配置ssh连接本地wsl方法

1、首先需要安装插件Remote-SSH 2、其次在wsl子系统中安装ssh服务并设置允许密码登入 3、开启ssh服务并查看wsl子系统的IP地址 4、返回vscode里面的Remote SSH插件,点击下图中的那个号进行设置: 首先输入的是连接名字 ,按enter键确认之后选…

施工企业数字化转型如何避免IT技术与企业管理的“两张皮”

工程项目是建筑产业的最基本单元,企业的生产经营数据都来源于项目,通过量化建造过程中的生产、管理要素,利用IoT、BIM、大数据、AI等核心技术,实时采集现场真实、唯一、精准、有效的工程项目资金、成本、进度、质量、安全、技术等…

NET:Spire.XLS 12.11.3 supports a variety of new formulas

Spire.XLS 12.11.3 supports a variety of new formulas 发现度娘破解版Spire.XLS for .NET is a professional Excel .NET API that can be used to create, read, write, convert and print Excel files in any type of .NET ( C#, VB.NET, ASP.NET, .NET Core, .NET 5.0, .…

【纯虚函数】设计一个形状类——矩形、圆形、三角形,分别计算三种当前图形的周长和面积

目录 一、纯虚函数 抽象类 纯虚函数概念: 抽象类的概念: 二、习题 题目: 代码: 测试结果: 一、纯虚函数 抽象类 纯虚函数概念: 是指没有具体实现的虚成员函数。用于这样的情况:设计一个…

QT+Python人脸表情特征识别

程序示例精选 QTPython人脸表情特征识别 前言 QTPython是非常经典的窗体编程组合,功能完善,可视化界面美观易维护,这篇博客针对人脸表情特征识别方面编写代码,代码整洁,规则,易读,对学习与使用P…

docker安装及优化

一、docker安装步骤详解 docker初期版本是1.13&#xff08;同一版本&#xff0c;开源&#xff09; ——》分类型 1.15 - 1.17 过程中分成两种。 ①开源社区 docker-ce ②企业版 docker-ee <span style"color:#000000"><span style"background-colo…

《web结课作业的源码》中华传统文化题材网页设计主题——基于HTML+CSS+JavaScript精美自适应绿色茶叶公司(12页)

&#x1f389;精彩专栏推荐 &#x1f4ad;文末获取联系 ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 &#x1f482; 作者主页: 【主页——&#x1f680;获取更多优质源码】 &#x1f393; web前端期末大作业&#xff1a; 【&#x1f4da;毕设项目精品实战案例 (10…

石化技术杂志石化技术杂志社石化技术编辑部2022年第10期目录

工业、生产《石化技术》投稿&#xff1a;cnqikantg126.com 衰减全反射傅里叶变换红外光谱测定溴化丁基橡胶中硬脂酸钙含量 俞培富;王晗;李振;邓洁;宋轶;姜旭鞠; 1-292 聚丙烯催化剂均聚性能实验研究 关健;付玉祥; 3-5 无损检测在石油钻具失效检验中的应用 李梅英;吕…

pandas中read_csv和to_csv、read_hdf和to_hdf、read_json和to_json函数及其他各类文件的读取与存储

pandas I/O API 是一组访问的顶级读取器函数&#xff0c;如 pandas.read_csv&#xff08;&#xff09;&#xff0c;通常返回一个 pandas 对象。相应的编写器函数是访问的对象方法&#xff0c;如 DataFrame.to_csv&#xff08;&#xff09; 一、read_csv和to_csv pandas.read_…