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 …...
EZ-Cube简易款下载器烧写使用方法
一、硬件连接 跟目标芯片接4根线 VCC、GND、TOOL、REST 四根线,如果板子芯片自己外接电源的,VCC 线可以不接。 二、 安装烧写软件和驱动 烧写软件:https://download.csdn.net/download/Stark_/87444744?spm1001.2014.3001.5503 驱动程序&a…...
sql server安装并SSMS连接
博主简介:原互联网大厂tencent员工,网安巨头Venustech员工,阿里云开发社区专家博主,微信公众号java基础笔记优质创作者,csdn优质创作博主,创业者,知识共享者,欢迎关注,点赞ÿ…...
Python_pytorch (二)
python_pytorch 小土堆pytotch学习视频链接 from的是一个个的包(package) import 的是一个个的py文件(file.py) 所使用的一般是文件中的类(.class) 第一步实例化所使用的类,然后调用类中的方法(def) Torchvision 数据集 数据集使用(CI…...
java手机短信验证,并存入redis中,验证码时效5分钟
目录 1、注册发送短信账号一个账号 2、打开虚拟机,将redis服务端打开 3、创建springboot工程,导入相关依赖 4、写yml配置 5、创建controller层,并创建controller类 6、创建service层,并创建service类 7、创建工具类&#x…...
kubectl命令控制远程k8s集群(Windows系统、Ubuntu系统、Centos系统)
文章目录1. 本地是linux2. 本地是Windows1. 本地是linux 安装kubectl命令 法一:从master的/usr/bin目录下拷贝kubectl文件到本机/usr/bin目录下法二:GitHub下载kubectl文件 在家目录下创建.kube目录config文件 法一:将master上对应用户的~/.…...
【求解器-COPT】COPT的版本更新中,老版本不能覆盖的问题
【求解器-COPT】COPT的版本更新中,老版本不能覆盖的问题方法1方法2如果license还是找不到作者:刘兴禄 参考网址: COPT的下载和配置步骤如下: 教程 | Windows系统下如何安装COPT求解器并配置许可文件: https://zhuan…...
Vue3.0文档整理:一、简介
1.1:什么是vue? Vue是一款用于构建用户界面的javascript框架;它基于标准HTML、CSS和Javascript构建,并提供了一套声明式、组件化的编程模型,帮助你高效的开发用户界面。 1.2:MVVM工作原理 MVVM指的是model、view和vie…...
vue2 diff算法及虚拟DOM
概括:diff算法,虚拟DOM中采用的算法,把树形结构按照层级分解,只比较同级元素,不同层级的节点只有创建和删除操作。 一、虚拟DOM (1) 什么是虚拟DOM? 虚拟 DOM (Virtual DOM,简称 VDOM) 是一种…...
Ray和极客们的创新之作,2月18日来发现
所在论坛:数据库技术创新&云原生论坛分享时段:2.18 10:30-11:00分享主题:云原生数据库PieCloudDB :Unbreakable安全特性剖析分享嘉宾:王淏舟,拓数派资深研发工程师 由中国开源软件推进联盟PostgreSQL分…...
Dubbo 源码分析 – 集群容错之 Router
1. 简介 上一篇文章分析了集群容错的第一部分 – 服务目录 Directory。服务目录在刷新 Invoker 列表的过程中,会通过 Router 进行服务路由。上一篇文章关于服务路由相关逻辑没有细致分析,一笔带过了,本篇文章将对此进行详细的分析。首先&…...
网站制作价/成品网站1688入口网页版怎样
使用内部(com.android.internal)和隐藏(hide)API手记 内部API和隐藏API的不同隐藏API隐藏是为了防止开发人员使用SDK中未完成或者未稳定(接口和架构方面看)的部分。比如,Bluetooth API在API Level 5(android 2.0)之前就…...
网站录入信息 前台查询功能怎么做/seo引擎优化平台培训
广东科技报讯(记者 刘肖勇 通讯员 韩战锋)8月4日,为期三天的“第三届粤港澳大湾区机器人大赛暨第十届亚洲机器人锦标赛中国选拔赛南大区赛”(以下简称“第三届粤港澳大湾区机器人大赛”)在香港中文大学(深圳)礼文楼隆重开幕,深圳市科学技术协会党组书记林…...
免费自己制作网站方法/辽源seo
先去下载https://dev.mysql.com/downloads/mysql/解压完是这个样子将这个文件放入到C盘并将文件名字改掉成MySQL配置初始化的my.ini文件的文件解压后的目录并没有的my.ini文件,没关系可以自行创建在安装根目录下添加的my.ini(新建文本文件,将文件类型改为…...
今天新冠病毒最新消息/怎么做seo网站关键词优化
pycharm同时使用python2.7和python3.5设置方法 - CSDN博客https://blog.csdn.net/qwerty200696/article/details/53015922转载于:https://www.cnblogs.com/jyfootprint/p/9417006.html...
做网站有哪些要求/企业培训有哪些方面
华为P30系列是华为在今年4月份推出的新品,凭借着超强的拍照能力以及天空之境配色广受喜爱。而在近日,LV为华为P30系列推出了专属手机壳,售价3050元,在官网和北京、上海的LV线下店开售。华为P30系列是华为在今年4月份推出的新品&am…...
山东省住房和城乡建设厅网站首页/百度如何推广产品
前言 Matlab已经成为画曲线图最好用的语言之一了, 但是许多人并没有发现他的最好用之处——相比于大部分语言,需要记住一堆API函数才能绘制出想要的曲线, matlab提供了可视化的界面进行傻瓜式的画图操作, 实现指哪打哪的功能而不…...