C++ operator new和operator delete的深入讲解

 个人主页:Jason_from_China-CSDN博客

所属栏目:C++系统性学习_Jason_from_China的博客-CSDN博客

所属栏目:C++知识点的补充_Jason_from_China的博客-CSDN博客

前言

关于operator new和operator delete我们需要明确一个概念,这两个都是一个函数,和malloc,free一样都是一个函数,但是这里需要明确的是,这里只是类似,不是一样。

operator new语法结构

语法结构

#include<iostream>
int main()
{//标准的分配内存的空间形式//分配一个内置类型,int内置类型的空间void* ptr1 = operator new(sizeof(int));//分配一个数组形式的内存空间void* ptr4 = operator new[](10 * sizeof(int));//这样的形式也是可以使用的,但是可能会出现问题,因为operator new是一个没有初始化,也就是未定义的内存空间//这样分配内存容易导致错误访问,所以还是建议使用标准化来分配内存空间//void* ptr2 = operator new(10 * sizeof(int));//void* ptr3 = operator new[](sizeof(int));//void* ptr4 = operator new[](10 * sizeof(int));return 0;
}

operator delete语法结构

#include<iostream>
int main()
{//标准的分配内存的空间形式//分配一个内置类型,int内置类型的空间void* ptr1 = operator new(sizeof(int));//分配一个数组形式的内存空间void* ptr4 = operator new[](10 * sizeof(int));//这样的形式也是可以使用的,但是可能会出现问题,因为operator new是一个没有初始化,也就是未定义的内存空间//这样分配内存容易导致错误访问,所以还是建议使用标准化来分配内存空间//void* ptr2 = operator new(10 * sizeof(int));//void* ptr3 = operator new[](sizeof(int));//void* ptr4 = operator new[](10 * sizeof(int));//operator new和delete这里是函数,所欲我们销毁的时候是函数的形式销毁,销毁的语法结构//释放单个内存空间//释放内存空间、标准化释放内存空间operator delete(ptr1);operator delete[](ptr4);return 0;
}

operator new+operator delete原理讲解

关于operator new

  • operator new我们可以看出来,其实new是operator new的一个封装,因为new在使用的时候会调用operator new
  • operator new的底层实现上面是调用malloc来实现开辟空间的


 

关于operator delete

  • 从operator delete我们可以看出来,delect本质也是对operator delete函数的封装,再严谨的讲解就是,是对free的封装,free是对free_dbg(p,_NORMAL_BLOCK)的封装
  • 所以我们可以更清晰的看出,operator delete是一个函数,不是关键字
  • delete是关键字,不是函数

operator new+operator delete和new+delete的深入对比

一、内置类型

  1. 对于内置类型,new 和 malloc、delete 和 free 基本类似。不同在于:new/delete 申请和释放单个元素空间,new []/delete [] 申请和释放连续空间;new 申请空间失败会抛异常,malloc 失败返回 NULL。
  2. 抛异常(就是告诉你哪里有错,并且继续运行程序)

二、自定义类型 new 的原理

  1. 调用 operator new 函数申请空间,底层类似 malloc(malloc 不抛异常)。
  2. 在申请的空间上执行构造函数完成对象构造。

三、自定义类型 delete 的原理

  1. 在空间上执行析构函数清理对象资源,本质类似 free 的调用。
  2. 调用 operator delete 函数释放对象空间。

四、new T [N] 的原理

  1. 调用 operator new [] 函数实际在其中调用 operator new 完成 N 个对象空间申请。
  2. 在申请的空间上执行 N 次构造函数。

五、delete [] 的原理

 
  1. 在释放的对象空间上执行 N 次析构函数,清理 N 个对象资源。
  2. 调用 operator delete [] 释放空间,实际在其中调用 operator delete。

operator new+operator delete和new+delete使用时候的注意事项

不要交错使用,很容易导致资源使用出现问题

  • operator new只是开辟空间,不会进行初始化的
  • operator delete是只是销毁空间,不会清理资源的
  • new,在开辟空间的时候会初始化并且构建资源
  • delete,销毁空间的时候会调用构造函数销毁资源
  • 知道,尽量不要交错使用就可以
#include<iostream>
using namespace std;class A
{
public:A(int capacity = 4, int size = 0):_Capacity(capacity), _size(size), _arr(nullptr){//创建空间_arr = new int[_Capacity];printf("A()");}~A() {//这里释放我们是需要匹配方括号,这里是释放数组形式的内容,自适应找到需要释放的内存delete[] _arr;_Capacity = 4;_size = 0;printf("~A()");}private:int* _arr;int _Capacity;int _size;
};//operator new创建空间,new构造
//我们需要使用 operator delete先销毁空间,再使用delete销毁资源
//并且是不能直接使用delete来进行销毁空间的,因为我们创建的空间是未定义的,new构造之后我们是会申请资源甚至空间的
//如果直接用delect销毁不使用operator delete销毁就会导致空间没有销毁
//如果只是使用operator delete销毁空间,就会导致资源没有销毁
//并且此时还应该先试用delete来销毁资源 再销毁空间
int main()
{A* p = new A[10];delete[] p;printf("\n");void* ptr1 = operator new[](10 * sizeof(A));//初始化,我们也可以进行定位new进行初始化,定位new里面我们会进行讲解for (int i = 0; i < 10; ++i) {new (static_cast<A*>(ptr1) + i) A(i * 10);}// 使用这些 A 对象// 销毁这些对象for (int i = 0; i < 10; ++i) {(static_cast<A*>(ptr1) + i)->~A();}operator delete[](ptr1);return 0;
}

  • operator new创建空间,new构造
  • 我们需要使用 operator delete先销毁空间,再使用delete销毁资源并且是不能直接使用delete来进行销毁空间的,因为我们创建的空间是未定义的,new构造之后我们是会申请资源甚至空间的
  • 如果直接用delect销毁不使用operator delete销毁就会导致空间没有销毁
  • 如果只是使用operator delete销毁空间,就会导致资源没有销毁
  • 并且此时还应该先使用delete来销毁资源 再使用operator delete销毁空间

定位new表达式(placement-new) (了解)

定位new主要使用的区域在于内存池,所以这里作为了解进行学习

一、在特定内存位置构造对象

  1. 可以在预先分配好的内存区域中创建对象,而不依赖于默认的内存分配机制。例如,使用operator new或其他方式分配了一块内存后,可以使用定位new在这块内存上构造对象。
  2. 语法形式为:new (pointer) Type(args...),其中pointer是指向已分配内存的指针,Type是要构造的对象类型,args...是构造函数的参数。
  3. 当使用普通的newdelete操作符时,delete会自动调用对象的析构函数并释放内存。但是对于通过定位new创建的对象,由于没有通过常规的内存分配机制,仅仅使用delete或者operator delete来释放内存不会自动调用析构函数。
  4. 此时我们发现可以用operator new开辟空间,new构造没有那么麻烦了,我们可以直接定位,可以直接看下面代码,但是这里有问题的就是不支持显示构造,但是支持显示析构

#include<iostream>
using namespace std;
class A
{
public:A(int capacity = 4, int size = 0):_Capacity(capacity), _size(size), _arr(nullptr){//创建空间_arr = new int[_Capacity];printf("A()");}~A() {//这里释放我们是需要匹配方括号,这里是释放数组形式的内容,自适应找到需要释放的内存delete[] _arr;_Capacity = 4;_size = 0;printf("~A()");}private:int* _arr;int _Capacity;int _size;
};int main()
{//正常函数的调用A* p = new A[10];delete[] p;printf("\n");//定位的使用,operator new创建一个空间,new定位进行构造void* ptr1 = operator new[](10 * sizeof(A));new(ptr1) A[10];//定位不支持显示构造,必须有默认构造//delete[] ptr1;//定位是需要显示调用析构函数来进行释放资源的。直接使用delect自动释放资源是不能实现的for (int i = 0; i < 10; i++){//static_cast强制类型转化关键字//<A*>转化为A类型//(ptr1) + i)->~A();循环显示调用析构函数(static_cast<A*>(ptr1) + i)->~A();}operator delete[](ptr1);return 0;
}

二、与内存池等技术结合使用

  1. 在一些高性能场景下,为了避免频繁的内存分配和释放开销,可以使用内存池预先分配一大块内存,然后在需要创建对象时使用定位new在内存池中选取合适的位置构造对象。
  2. 这样可以提高内存分配的效率,减少内存碎片的产生。

三、资源管理和对象生命周期控制

  1. 通过定位new,可以更精细地控制对象的构造和析构时机,特别是在一些复杂的资源管理场景中。
  2. 例如,可以在特定的资源初始化后,在与之相关的内存位置构造对象,确保资源和对象的生命周期紧密关联。

四、注意事项

  1. 使用定位new构造的对象,在销毁时需要手动调用析构函数,而不能直接使用delete来释放内存,因为delete会尝试释放由默认内存分配机制分配的内存,而不是定位new所使用的内存。
  2. 例如:new (ptr) Type(args...);构造的对象,在销毁时应该使用ptr->~Type();来调用析构函数。

malloc/free 和 new/delete 的区别

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

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

相关文章

15.5 JDBC数据库编程5——DAO

目录 15.1.1 引言 实体类Product.java 异常类DaoException.java Dao.java ProductDao.java ProductDaoImpl.java ProductDaoTest.java 15.1.1 引言 Java是面向对象编程语言&#xff0c;主要操作对象&#xff0c;而关系数据库的数据并不是对象&#xff0c;Java程序插入…

linux线程 | 线程的控制(下)

前言&#xff1a; 本节内容是线程的控制部分的第二个小节。 主要是列出我们的线程控制部分的几个细节性问题以及我们的线程分离。这些都是需要大量的代码去进行实验的。所以&#xff0c; 准备好接受新知识的友友们请耐心观看。 现在开始我们的学习吧。 ps:本节内容适合了解线程…

对MVC详细解读

一、MVC模式的详细组成部分 1. 模型&#xff08;Model&#xff09; 数据结构&#xff1a; 模型通常使用类或结构来定义应用程序的数据结构。例如&#xff0c;在Ruby on Rails中&#xff0c;模型通常与数据库表相对应&#xff0c;使用Active Record模式。 数据访问层&#xff1…

动态内存管理(C语言 VS C++)

目录 一.动态内存管理的前置知识 1.栈区 a.栈区的特点 b.注意事项 2.堆区 a.堆区的特点 b.注意事项 3.全局/静态区 a.作用域和生命周期 b.注意事项 4.常量区 二.C语言动态内存管理 1.malloc 函数 a.接口简介与使用实例 b.注意要点 2.calloc 函数&#xff1a; 3.…

Flink Web UI 是使用和调试保姆级教程(持续更新)

Flink Web UI 是调试和监控 Flink 应用程序的重要工具&#xff0c;通过它&#xff0c;你可以实时查看正在运行的 Flink 任务的详细信息&#xff0c;包括作业的状态、性能指标、各子任务的运行情况、故障恢复情况等。Flink Web UI 的这些功能为开发者和运维人员提供了调试和优化…

化学元素分子量、氧化物系数计算python类

在网上找到的分子量计算类&#xff0c;做了少量修改,有原子量、分子量、氧化物系数的计算。 import re wt_dict{ #该原子量数据从CRC手册第95版提取。"H": 1.008,"He": 4.002602,"Li": 6.94,"Be": 9.0121831,"B": 10.…

【入门篇】2.4 map映射文件解析

目录 一,编译产物 1.1 .o 文件(目标文件): 1.2 .hex 文件(十六进制文件) 1.3 .bin 文件(二进制文件) 1.4 .elf 文件(可执行链接格式文件) 1.5 .map 文件(映射文件) 1.6 .lst 文件(列表文件) 二,map文件解析 2.1 程序段交叉引用关系(Section Cross Refe…

Git基础-配置http链接的免密登录

问题描述 当我们在使用 git pull 或者 git push 进行代码拉取或代码提交时&#xff0c; 若我们的远程代码仓库是 http协议的链接时&#xff0c;就是就会提示我们进行账号密码的登录。 每次都要登录&#xff0c;这未免有些麻烦。 本文介绍一下免密登录的配置。解决方案 1 执行…

如何在CSS中修改滚动条样式

修改滚动条样式在CSS中是一个有趣而常见的需求&#xff0c;特别是当你希望网页设计更加个性化时。虽然并不是所有浏览器都完全支持修改滚动条样式&#xff0c;但我们可以使用一些专门的CSS选择器来控制滚动条外观。以下是一个详细讲解&#xff0c;适合整理成博客发布。 如何在C…

软考系统分析师知识点十三:软件需求工程

前言 今年报考了11月份的软考高级&#xff1a;系统分析师。 考试时间为&#xff1a;11月9日。 倒计时&#xff1a;24天。 目标&#xff1a;优先应试&#xff0c;其次学习&#xff0c;再次实践。 复习计划第一阶段&#xff1a;扫平基础知识点&#xff0c;仅抽取有用信息&am…

FPGA采集adc,IP核用法,AD驱动(上半部分)

未完结&#xff0c;明天补全 IP核&#xff1a;集成的一个现有的模块 串口写好后基本不会再修改串口模块内部的一些逻辑&#xff0c;将串口.v文件添加进来&#xff0c;之后通过他的上层的接口去对他进行使用&#xff0c;所以我们打包IP&#xff0c;之后就不用去添加源文件了&a…

仿 Mac 个人网站开发 |项目复盘

一、前言 1.1 灵感来源 早年有幸看到国外大佬做的一个 基于 Web 的 Windows XP 桌面娱乐系统, 那时刚好有搭建一个个人博客的想法, 所以就想是否可以基于 WEB 实现一个仿 Mac UI 的个人博客, 以应用的形式来展示博客各个功能! 1.2 相关链接(求个 Star) 前端开源代码后端开源…

Linux之实战命令32:chroot应用实例(六十六)

简介&#xff1a; CSDN博客专家、《Android系统多媒体进阶实战》一书作者 新书发布&#xff1a;《Android系统多媒体进阶实战》&#x1f680; 优质专栏&#xff1a; Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 优质专栏&#xff1a; 多媒体系统工程师系列【…

【MySQL】入门篇—SQL基础:SQL语言概述

SQL&#xff08;Structured Query Language&#xff0c;结构化查询语言&#xff09;是一种用于管理和操作关系数据库的标准语言。随着信息技术的快速发展&#xff0c;数据成为企业和组织最重要的资产之一。有效地存储、查询和管理数据对于业务决策和运营至关重要。 SQL作为与关…

Java类与对象的分配机制

在Java中&#xff0c;类和对象是不同的概念。 类是一种数据类型&#xff0c;它定义了对象的行为和属性。类可以包含成员变量和方法。 对象是类的实例&#xff0c;它是在程序运行时根据类创建的。每个对象都有自己独立的内存空间&#xff0c;可以访问类中定义的成员变量和方法…

ali 231普通滑块82y版本

有需求可以联系博主 let v Died_in2021

【含开题报告+文档+PPT+源码】基于人脸识别的课堂考勤系统的设计与实现

开题报告 随着科技的不断发展&#xff0c;人脸识别技术已经逐渐渗透到各个领域&#xff0c;包括教育领域。传统的课堂考勤方式通常依赖于学生签到或教师手动记录&#xff0c;这种方式存在着许多不足之处&#xff0c;例如容易出现人为错误、耗费时间和资源等。为了解决这些问题…

诺贝尔经济学奖历史名单数据集(1969-2024年)

2024年诺贝尔经济学奖授予了达龙阿西莫格鲁&#xff08;Daron Acemoglu&#xff09;、西蒙约翰逊&#xff08;Simon Johnson&#xff09;和詹姆斯A罗宾逊&#xff08;James A. Robinson&#xff09;&#xff0c;以表彰他们在理解制度如何影响经济发展方面的贡献。&#xff08;“…

mysql学习教程,从入门到精通,sql序列使用(45)

sql序列使用 在SQL中&#xff0c;序列&#xff08;Sequence&#xff09;是一种数据库对象&#xff0c;用于生成唯一的数值&#xff0c;通常用于自动递增的主键。不同的数据库管理系统&#xff08;DBMS&#xff09;对序列的支持和语法可能有所不同。以下是一些常见的DBMS&#…

jmeter用csv data set config做参数化

在jmeter中&#xff0c;csv data set config的作用非常强大&#xff0c;用它来做批量测试和参数化非常好用。 csv data set config的常用配置项如下&#xff1a; Variable Names处&#xff0c;写上源文件中的参数名&#xff0c;用于后续接口发送请求时引用 Ignore first line…