C++的 new 和 delete
文章目录
- 一、new 和 delete 的使用
- 二、operator new 和 operator delete 函数
- 三、new 和 delete 的实现原理
- 四、申请空间和释放空间应配套使用
- 五、定位 new 表达式
- 六、malloc/free 和 new/delete 的区别
C语言的动态内存管理函数(malloc、calloc、realloc、free) 虽然可以继续在 C++ 使用,但是对于自定义类型成员而言,这些函数不会自动调用构造函数和析构函数,于是 C++ 增加了 new 和 delete 关键字
一、new 和 delete 的使用
new 和 delete 用于在堆上申请或释放一个元素的空间,new[] 和 delete[] 用于在堆上申请或释放一块连续的空间,对于自定义类型空间的开辟,new 和 delete 还会调用构造函数和析构函数
#include <iostream>using namespace std;class Demo
{
public:Demo(int a1 = 10, int a2 = 20): _a1(a1), _a2(a2){cout << "Demo()" << endl;}void print(){cout << _a1 << " " << _a2 << endl;}~Demo(){cout << "~Demo()" << endl;}private:int _a1;int _a2;
};void printIntArr(int* arr, int len)
{for (int i = 0; i < len; ++i){cout << arr[i] << " ";}cout << endl;
}void printDemoArr(Demo* arr, int len)
{for (int i = 0; i < len; ++i){arr[i].print();}cout << endl;
}int main()
{//用 new 申请一个内置类型变量的空间int* pint1 = new int;cout << *pint1 << endl; //输出 -842150451//使用括号中的值初始化变量int* pint2 = new int(5);cout << *pint2 << endl; //输出 5//用 delete 释放一个变量的空间delete pint1;delete pint2;//用 new 申请一个自定义类型对象的空间,申请后会自动调用构造函数Demo* pd1 = new Demo; //输出 Demo()pd1->print(); //输出 10 20//自定义类型会根据括号中的参数调用对应的构造函数Demo* pd2 = new Demo(5, 5); //输出 Demo()pd2->print(); //输出 5 5//用 delete 释放一个变量的空间,释放前会自动调用析构函数delete pd1; //输出 ~Demo()delete pd2; //输出 ~Demo()//对内置类型用 new[] 开辟一块连续的空间int* pint3 = new int[5]; //[]中表示开辟整形的个数printIntArr(pint3, 5); //输出 -842150451 -842150451 -842150451 -842150451 -842150451//用花括号中的值初始化开辟的连续空间,未给值的为 0int* pint4 = new int[5]{ 1, 2, 3, 4 }; printIntArr(pint4, 5); //输出 1 2 3 4 0//对内置类型用 delete[] 释放一块连续的空间delete[] pint3;delete[] pint4;//对自定义类型用 new[] 开辟一块连续的空间//申请后会对空间自动调用构造函数 5 次Demo* pd3 = new Demo[5]; //输出 5 行 Demo()printDemoArr(pd3, 5); //输出 5 行 10 20//用花括号中的值初始化开辟的连续空间//花括号中如果用小括号会被认为是逗号表达式,会去调用单参的构造函数//调用多参构造函数应在花括号中使用花括号,未给的值根据构造函数决定Demo* pd4 = new Demo[5]{ (1, 2), {5}, {5, 10}}; //输出 5 行 Demo()printDemoArr(pd4, 5); //输出 第一行 2 20,第二行 5 10 第三行 5 10,两行 10 20//对自定义类型用 delete[] 释放一块连续的空间//释放之前会对空间自动调用析构函数 5 次delete[] pd3; //输出 5 行 ~Demodelete[] pd4; //输出 5 行 ~Demoreturn 0;
}
二、operator new 和 operator delete 函数
operator new 和 operator delete 是系统提供的全局函数,不是 new 和 delete 的运算符重载函数
-
operator new 底层是通过 malloc 函数来申请空间,当空间申请成功时直接返回,失败时抛出异常(不会返回 nullptr),operator new 函数可以像 malloc 一样使用,只是失败时的处理不同
-
operator delete 和 free 底层都是是通过 _free_dbg 函数释放空间,只不过 operator delete 会对释放前后进行一些检查
#include <iostream>using namespace std;int main()
{//operator new 和 malloc 使用方法一样//operator new 申请空间失败时抛异常int* pi = (int*)operator new(sizeof(int) * 4);//operator delete 和 free 使用方法一样,都会调用 _free_dbg//operator delete 在释放空间时会做一些检查operator delete(pi);return 0;
}

operator new[] 和 operator delete[] 也是系统提供的全局函数,内部是通过调用 operator new 和 operator delete 函数

三、new 和 delete 的实现原理
如果是内置类型,new 和 delete 调用 operator new 和 operator delete,new[] 和 delete[] 调用 operator new[] 和 operator delete[]
如果是自定义类型:
#include <iostream>using namespace std;class Demo
{
public:Demo(int a1 = 10, int a2 = 20);~Demo();private:int _a1;int _a2;
};Demo::Demo(int a1, int a2): _a1(a1), _a2(a2)
{cout << "Demo()" << endl;
}Demo::~Demo()
{cout << "~Demo()" << endl;
}int main()
{Demo* pd1 = new Demo(5, 5);delete pd1;Demo* pd2 = new Demo[2]{ {1, 2}, {2, 3} };delete[] pd2;return 0;
}
- new:
1. 调用 operator new 函数申请空间
2. 在申请的空间上执行构造函数,完成对象的构造 - delete:
1. 在空间上执行析构函数,完成对象中资源的清理工作
2. 调用operator delete函数释放对象的空间

- new 类型[N]:
1. 调用operator new[] 函数,实际上是在 operator new[] 中调用 operator new 函数完成 N 个对象空间的申请
2. 在申请的空间上执行 N 次构造函数 - delete[]:
1. 在释放的对象空间上执行 N 次析构函数,完成 N 个对象中资源的清理
2. 调用 operator delete[] 释放空间,实际上时在 operator delete[] 中调用 operator delete 来释放空间

四、申请空间和释放空间应配套使用
malloc/free、new/delete、new[]/delete[] 需要配套使用,否则总会有出问题的时候
下述代码不会报错,会产生内存泄漏
#include <iostream>using namespace std;class Stack
{
public:Stack(int capacity = 4): _a(new int[capacity]), _top(0), _capacity(capacity){}~Stack(){if (_a){delete[] _a;_top = _capacity = 0;}}private:int* _a;int _top;int _capacity;
};int main()
{Stack* ps = new Stack;//free(ps); //内存泄漏//delete 释放内存之前会调用析构函数delete ps; //正确写法return 0;
}

下述代码在 vs2022 下会崩溃
#include <iostream>using namespace std;class A
{
public:A(int a = 0): _a(a){cout << "A():" << endl;}~A(){cout << "~A():" << endl;}private:int _a;
};int main()
{A* p1 = new A[10];//free(p1); //崩溃delete[] p1; //正确写法A* p2 = new A[10];//delete p2; //崩溃delete[] p2; //正确写法return 0;
}

注意:不同的编译器处理可能不同,这里只代表在 vs2022 编译器中
五、定位 new 表达式
定位 new 表达式是在已开辟好的原始内存空间上调用构造函数初始化一个对象,使用格式:
new(place_address)type 或者 new(place_address)type(initializer-list)
place_address 必须是一个指针,initializer-list 是类型的初始化列表
定位 new 表达式在实际中一般是配合 内存池 使用,因为内存池分配出的内存没有初始化,并且构造函数不可以显示调用,所以如果是自定义类型的对象,需要使用定位 new 以进行显示调用构造函数进行初始化
#include <iostream>using namespace std;class A
{
public:A(int a = 0): _a(a){cout << "A()" << endl;}~A(){cout << "~A()" << endl;}private:int _a;
};//定位 new 又叫 replacement new
int main()
{//p1 现在指向的只是与 A 对象相同大小的一段空间,并不是一个对象,因为没有调用构造函数A* p1 = (A*)malloc(sizeof(A));new(p1)A; //调用无参的构造函数 输出 A()//可以手动调用析构函数,然后释放空间p1->~A(); //输出 ~A()free(p1);//p2 现在指向的只是与 A 对象相同大小的一段空间,并不是一个对象,因为没有调用构造函数A* p2 = (A*)operator new(sizeof(A));new(p2)A(10); //10 是参数,可以根据参数调用对应的构造函数 输出 A()p2->~A(); //输出 ~A()operator delete(p2);return 0;
}
六、malloc/free 和 new/delete 的区别
malloc/free 和 new/delete 的共同点是:都是从堆上申请空间,并且需要用户手动释放
不同的地方是:
- malloc 和 free 是函数,new 和 delete 是运算符
- malloc 申请的空间不会初始化,new 可以初始化
- malloc 申请空间时,需要手动计算空间大小并传递,new 只需在其后跟上空间的类型,如果是多个对象,[] 中指定对象个数即可
- malloc 的返回值为 void*,接收时必须强制类型转换,new 不需要,因为 new 后跟的是空间的类型
- malloc 申请空间失败时,返回的是NULL,因此使用时必须判空,new 不需要,但是 new 需要捕获异常
- 申请自定义类型对象时,malloc/free 只会开辟空间,不会调用构造函数与析构函数,而 new 在申请空间后会调用构造函数完成对象的初始化,delete 在释放空间前会调用析构函数完成空间中资源的清理
相关文章:
C++的 new 和 delete
文章目录一、new 和 delete 的使用二、operator new 和 operator delete 函数三、new 和 delete 的实现原理四、申请空间和释放空间应配套使用五、定位 new 表达式六、malloc/free 和 new/delete 的区别C语言的动态内存管理函数(malloc、calloc、realloc、free) 虽然可以继续在…...
MySQL 事务原理
文章目录1、事务1.1、ACID 特性1.1.1、原子性undo log1.1.2、一致性1.1.3、* 隔离性1.1.4、持久性redo log1.2、事务控制语句2、隔离级别2.1、隔离级别的分类2.1.1、读未提交 RU2.1.2、读已提交 RC2.1.3、可重复读 RR2.1.4、串行化 SC2.2、并发事务读异常2.2.1、* 脏读2.2.2、*…...
软件测试面试自我介绍/项目介绍居然还有模板?我要是早点发现就好了
目录 1、自我介绍 2、项目介绍 2.1、最全电商项目介绍 2.2、电商项目介绍 2.3、在线教育项目介绍 2.4、互联网金融项目介绍 总结 1、自我介绍 以XXX简历来举例(参照下面的案例,编写你的自我介绍,框架就是:我是谁࿰…...
new RegExp的使用
1.RegExp是什么 当检索某个文本时,可以使用一种模式来描述要检索的内容。RegExp 就是这种模式 RegExp 对象用于存储检索模式。 var patt1new RegExp("e");当使用该 RegExp 对象在一个字符串中检索时,将寻找的是字符 “e” g :表…...
供应商管理软件如何选型 好用的供应商管理软件推荐
供应商管理是采购中的重要环节。对于很多企业来说,做好内部供应商管理就能在行业竞争中提升自身的效益与竞争能力,供应商已成为一种战略筹码。 但在企业进行供应商管理过程中,往往会遇到供应商信息数据收集不全、等级划分不合理、绩效评价机…...
Python3遍历文件夹提取关键字及其附近字符
要求: 1,遍历文件夹下所有的.xml文件 2,从.xml文件中提取关键字以及左右十个字符 3,输出到excel 一:遍历文件夹找到所有xml文件及其路径 for root, dirs, files in os.walk(self.inputFilePath):for file in files:…...
「1」线性代数(期末复习)
🚀🚀🚀大家觉不错的话,就恳求大家点点关注,点点小爱心,指点指点🚀🚀🚀 第一章 行列式 行列式是一个数,是一个结果三阶行列式的计算:主对角线的乘…...
C++7:STL-模拟实现vector
目录 vector的成员变量 构造函数 reserve size() capacity() push_back 一些小BUG 赋值操作符重载 析构函数 【】操作符重载 resize pop_back Insert 迭代器失效 erase 二维数组问题 总结一下 vector,翻译软件会告诉你它的意思是向量,但其…...
笑死,面试官又问我SpringBoot自动配置原理
面试官:好久没见,甚是想念。今天来聊聊SpringBoot的自动配置吧? 候选者:嗯,SpringBoot的自动配置我觉得是SpringBoot很重要的“特性”了。众所周知,SpringBoot有着“约定大于配置”的理念,这一…...
分布式缓存服务DCS-企业版性能更强,稳定性更高
背景介绍 近年来,随着各行业业务需求急速增加,数据量和并发访问量呈指数级增长,原来只能依附于关系型数据库的传统“缓存”逐渐难以支撑上层业务,开源Redis也面临着如“容量有限”、 “可靠性有限”、 “数据重复拷贝,…...
HTTP基本原理
目录URL简单定义格式HTTP和HTTPSHTTP的请求过程。请求响应响应体HTTP2.0总结URL 简单定义 通过一个链接,使我们可以找到网络上的某个资源,这个链接就是URL。 格式 URL并不是随便写的,而是有固定的格式。基本的组成格式如下。 schme://[us…...
【云原生】Kubernetes(k8s)最新版本详细保姆级安装教程
前言 Kubernetes简称k8s,是一个开源的,用于管理云平台中多个主机上的容器化的应用,k8s目标是让部署容器化的应用简单并且高效,k8s提供了应用部署,规划,更新,维护的一种机制。 本文是总结了在安…...
JVM - 类加载,连接和初始化
目录 类加载和类加载器 概述 类加载要完成的功能 加载类的方式 类加载器 类加载器的关系 类加载器说明 双亲委派模型 工作过程如下: 双亲委派模型说明: 破坏双亲委派模型: 类连接和初始化 类连接主要验证的内容 类连接中的解析…...
[carla]关于odometry坐标中的角度坐标系 以及 到地图的映射问题
1.获取车辆的Odometry原始信息 在carla中,通过订阅/carla/ego_vecle/odometry 可以查看车辆的全局位置信息,例如: > header: seq: 118872stamp: secs: 5946nsecs: 5720187frame_id: "map" child_frame_id: "ego_vehicle" pos…...
Python 正则表达式
正则表达式主要用来查找和匹配字符串的。 一、正在表达式基础 字符 描述 示例 TIY\ 示意特殊序列(也可用于转义特殊字符)如:空白字符 "\s" . 任何字符(换行符除外) "he..o" ^ 起始于 "^h…...
spark03-读取文件数据分区数量个数原理
代码val conf: SparkConf new SparkConf().setMaster("local").setAppName("wordcount")val sc: SparkContext new SparkContext(conf)val rdd: RDD[String] sc.textFile("datas/1.txt",2)rdd.saveAsTextFile("output")数据格式 &a…...
操作系统(day08)内存
存储单元 内存的几个基本概念 存储单元 内存地址从0开始,每个地址对应一个存储单元 存储单元大小根据计算机按照什么方式编址 按字节编址 则每个存储单元大小为一字节,即1B,即8个二进制位按字编址 看这个计算的字长是多少位,如…...
11- 聚类算法 (KMeans/DBSCAN/agg) (机器学习)
聚类算法 聚类算法和降维算法那都属于无监督算法。KMeans 是以一个值为中心, 然后所有其他点到该点距离最小值的累积和。 kmeans KMeans(n_clusters3) # n_clusters 分类数量 kmeans.fit(data.iloc[:,1:]) # 无监督,只需要给数据X就可以 DBSCAN 算法是…...
日日顺供应链|想要看清供应链发展趋势,先回答这三个问题
技术变革如何支撑供应链及管理服务的发展? 数字化与科技化开始承托供应链管理能力的升级与变革? 如何从客户需求的纬度反推供应链及管理服务的模式变革?在过去的三年中,我国的供应链企业经受了最为极端的挑战,但当下&a…...
5守护进程与线程
进程组 多个进程的集合,第一个进程就是组长,组长进程的PID等于进程组ID。 进程组生存期:进程组创建到最后一个进程离开(终止或转移到另一个进程组)。与组长进程是否终止无关。 一个进程可以为自己或子进程设置进程组 ID 相关函数 pid_t …...
rknn优化教程(二)
文章目录 1. 前述2. 三方库的封装2.1 xrepo中的库2.2 xrepo之外的库2.2.1 opencv2.2.2 rknnrt2.2.3 spdlog 3. rknn_engine库 1. 前述 OK,开始写第二篇的内容了。这篇博客主要能写一下: 如何给一些三方库按照xmake方式进行封装,供调用如何按…...
R语言AI模型部署方案:精准离线运行详解
R语言AI模型部署方案:精准离线运行详解 一、项目概述 本文将构建一个完整的R语言AI部署解决方案,实现鸢尾花分类模型的训练、保存、离线部署和预测功能。核心特点: 100%离线运行能力自包含环境依赖生产级错误处理跨平台兼容性模型版本管理# 文件结构说明 Iris_AI_Deployme…...
[10-3]软件I2C读写MPU6050 江协科技学习笔记(16个知识点)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16...
网络编程(UDP编程)
思维导图 UDP基础编程(单播) 1.流程图 服务器:短信的接收方 创建套接字 (socket)-----------------------------------------》有手机指定网络信息-----------------------------------------------》有号码绑定套接字 (bind)--------------…...
Maven 概述、安装、配置、仓库、私服详解
目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...
Xen Server服务器释放磁盘空间
disk.sh #!/bin/bashcd /run/sr-mount/e54f0646-ae11-0457-b64f-eba4673b824c # 全部虚拟机物理磁盘文件存储 a$(ls -l | awk {print $NF} | cut -d. -f1) # 使用中的虚拟机物理磁盘文件 b$(xe vm-disk-list --multiple | grep uuid | awk {print $NF})printf "%s\n"…...
JavaScript基础-API 和 Web API
在学习JavaScript的过程中,理解API(应用程序接口)和Web API的概念及其应用是非常重要的。这些工具极大地扩展了JavaScript的功能,使得开发者能够创建出功能丰富、交互性强的Web应用程序。本文将深入探讨JavaScript中的API与Web AP…...
【从零学习JVM|第三篇】类的生命周期(高频面试题)
前言: 在Java编程中,类的生命周期是指类从被加载到内存中开始,到被卸载出内存为止的整个过程。了解类的生命周期对于理解Java程序的运行机制以及性能优化非常重要。本文会深入探寻类的生命周期,让读者对此有深刻印象。 目录 …...
在鸿蒙HarmonyOS 5中使用DevEco Studio实现企业微信功能
1. 开发环境准备 安装DevEco Studio 3.1: 从华为开发者官网下载最新版DevEco Studio安装HarmonyOS 5.0 SDK 项目配置: // module.json5 {"module": {"requestPermissions": [{"name": "ohos.permis…...
书籍“之“字形打印矩阵(8)0609
题目 给定一个矩阵matrix,按照"之"字形的方式打印这个矩阵,例如: 1 2 3 4 5 6 7 8 9 10 11 12 ”之“字形打印的结果为:1,…...
