“new出对象“原理的深层解密

在这里插入图片描述

🎈个人主页:🎈 :✨✨✨初阶牛✨✨✨
🐻推荐专栏1: 🍔🍟🌯C语言初阶
🐻推荐专栏2: 🍔🍟🌯C语言进阶
🔑个人信条: 🌵知行合一
🍉本篇简介:>:讲解C++中的有关内存管理知识,如何new出对象?
金句分享:
✨如果事与愿违,请相信另有安排.✨

前言

讲解C++中有关new的知识,与malloc进行对比,以及深入探索new的实现原理.

目录

  • 前言
  • 一、malloc和new的使用
    • 1.1 new创建内置类型(int等)
    • 1.2 new创建数组
    • 1.3 创建对象
    • 1.4 异常处理
  • 二、malloc和new的区别:(面试热门)
  • 三、new和delete的深层解密
    • 3.1 解密实现原理
    • 3.2 通过汇编指令验证

一、malloc和new的使用

C语言阶段,我们习惯使用malloc向内存申请空间,但是在C++阶段,我们习惯用new在动态内存中创建对象,为什么呢?

1.1 new创建内置类型(int等)

在创建内置类型时,new只是不需要进行强转和计算内置类型的大小,看起来更加简洁,方便.

	//malloc申请内置类型int* p1 = (int*)malloc(sizeof(int));free(p1);//new对比int* ptr1 = new int;delete ptr1;

1.2 new创建数组

new + 对象的类型 + [个数] + (初始化的值)

new + 对象的类型 + [个数] + {num1,num2,…}

需要注意的是,连续的多个空间须使用new[]delete[]搭配

	//申请数组int* p3 = (int*)malloc(sizeof(int) * 10);//赋值for (int i = 0; i < 10; i++){p3[i] = i;}//打印for (int i = 0; i < 10; i++){cout << p3[i] << " ";}cout << endl;// new创建数组int* ptr3 = new int[10]{0,1,2,3,4,5,6,7,8,9};for (int i = 0; i < 10; i++){cout << ptr3[i] << " ";}//释放free(p3);delete[] ptr3;

1.3 创建对象

如何使用new进行创建对象?

#include <iostream>
using namespace std;
#include<stdlib.h>class Date
{
public:Date():_year(2020),_month(6),_day(6){cout << "A()" << endl;}void print(){cout << _year << "-" << _month << "-" << _day << endl;}~Date(){cout << "~A()" << endl;free(_a);}
private:int _year;int _month;int _day;int* _a=nullptr;
};int main()
{//malloc出对象Date* d1 = (Date*)malloc(sizeof(Date));d1->print();free(d1);//new出对象Date* d2 = new Date;d2->print();delete d2;return 0;
}

运行结果:

-842150451–842150451–842150451
A()
2020-6-6
~A()

通过上段代码我们发现,malloc只是进行开空间的操作,对象并没有得到初始化操作.
new则是在开空间的同时,会调用对象的构造函数,将对象进行初始化.

free只是进行简单的释放申请的空间,如果对象中存在动态申请的成员,则无法进行释放.
delete会在释放申请的对象空间的同时,调用对象的析构函数,彻底的完成空间的清理工作.

1.4 异常处理

对于malloc函数,当malloc申请内存空间失败的时候,会返回一个NULL指针.
我们通常通过判断返回值是否为NULL来判断是否申请成功.

	int* a = (int*)malloc(10000* sizeof(int));if (a == NULL){perror("malloc a fail");//申请失败时,打印错误信息return 0;}

new失败不会返回NULL,而是通过抛出异常.
C++中,可以使用try-catch语句来捕获new操作符抛出的异常。new操作符在内存分配过程中如果失败,会抛出一个bad_alloc异常。

示例代码:

try {int* myArray = new int[10000]; // 分配一个包含10000个整数的数组// ...delete[] myArray; 
}
catch (const std::bad_alloc& e) {// 处理内存分配失败的异常std::cout << "内存分配失败: " << e.what() << std::endl;
}

在上述代码中,new操作符用于分配一个包含10000个整数的数组。如果内存分配失败,将抛出一个bad_alloc异常。catch语句块接收这个异常,并执行相应的处理代码。在这个示例中,异常被捕获后会打印一条错误消息。

需要注意的是,catch语句块中的参数类型应为const std::bad_alloc&,因为bad_alloc是标准异常类,它派生自std::exception,通常以常量引用的形式传递给异常处理代码。

二、malloc和new的区别:(面试热门)

C++中,mallocnew都用于在堆上分配内存,但有一些重要的区别。

  1. 语法和类型安全性mallocfree是函数,newdelete是操作符
    (1)malloc是C语言中的函数,malloc需要指定要分配的内存大小,并返回一个指向未初始化内存块的指针。
    (2)newC++中的运算符new可以直接在创建对象时进行初始化,并返回一个指向已经构造的对象的指针。new操作符会执行类型检查,确保分配的内存与对象类型匹配。

  2. 构造函数和析构函数调用
    (1)使用new分配内存时,会自动调用对象的构造函数进行初始化。
    (2)使用malloc分配内存时,不会调用对象的构造函数,需要手动调用构造函数初始化对象。
    (3)同样,使用delete释放new分配的内存时,会自动调用析构函数进行清理工作。而使用free释放malloc分配的内存时,不会自动调用析构函数,需要手动执行清理操作。

  3. 内存大小计算
    (1)使用malloc分配内存时,需要显式指定要分配的内存块的大小,以字节为单位。
    (2)使用new分配单个对象时,编译器会自动计算所需的内存大小,以对象的类型为基础。对于数组对象,需要使用new[]delete[],同样会自动计算所需的内存。

  4. 异常处理new在分配内存失败时,会抛出std::bad_alloc异常,而malloc在分配内存失败时,返回NULL指针。

  5. malloc的返回值为void*, 在使用时必须强转,new不需要,因为new后跟的是空间的类型

总的来说,new相对于malloc提供了更高级的、更安全的内存分配方式,能够自动调用构造函数和析构函数,执行类型检查,并提供异常处理。因此,在C++中,推荐使用newdelete来进行动态内存分配和释放。如果你需要使用C语言的库或与C代码进行交互,可以使用mallocfree

三、new和delete的深层解密

3.1 解密实现原理

学到这里,我们知道new会代用构造函数,还会抛出异常,那它究竟是怎么实现的呢?
在这里插入图片描述

operator new的实现

void *__CRTDECL operator new(size_t size) _THROW1(_STD bad_alloc)
{
void *p;
while ((p = malloc(size)) == 0)//通过mallo开空间if (_callnewh(size) == 0){// report no memory// 如果申请内存失败了,这里会抛出bad_alloc 类型异常static const std::bad_alloc nomem;_RAISE(nomem);}
return (p);
}

在这里插入图片描述

看不懂没关系,只需要知道operator delete调用了free函数即可

void operator delete(void *pUserData)
{_CrtMemBlockHeader * pHead;RTCCALLBACK(_RTC_Free_hook, (pUserData, 0));if (pUserData == NULL)return;_mlock(_HEAP_LOCK);  /* block other threads */__TRY/* get a pointer to memory block header */pHead = pHdr(pUserData);/* verify block type */_ASSERTE(_BLOCK_TYPE_IS_VALID(pHead->nBlockUse));_free_dbg( pUserData, pHead->nBlockUse );//调用了free函数__FINALLY_munlock(_HEAP_LOCK);  /* release other threads */__END_TRY_FINALLYreturn;
}

free的实现就是一个宏定义_free_dbg(p, _NORMAL_BLOCK)

#define   free(p)               _free_dbg(p, _NORMAL_BLOCK)

我们可以直接调用operator newoperator delete函数.

void test1()
{A* a1 = (A*)operator new (sizeof(A));A* a2 = (A*)malloc (sizeof(A));operator delete(a1);free(a2);
}
int main()
{test1();return 0;
}

发现operator new 的使用和malloc没什么区别,
只是一个抛异常.
一个返回NULL.
在这里插入图片描述

3.2 通过汇编指令验证

void test1()
{A* a1 = new A;delete a1;
}

通过调试窗口的反汇编窗口,我们查看A* a1 = new A;对应的汇编指令:
在这里插入图片描述
会发现,new操作符果然是调用operator new +构造函数.

查看delete操作符,由于vs编译器进行了再封装,我们需要进到下面这条指令里面去看:
在这里插入图片描述

不难发现,delete操作符=调用析构函数+调用operator delete函数
在这里插入图片描述

好的,本篇有关new操作符和delete操作符的相关知识就讲到这里了,希望对大家有所帮助.
如果觉得文章有帮助的话,可以来个一键三连吗?
在这里插入图片描述

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

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

相关文章

欧拉函数和最大公约数

分析&#xff1a;如果两个数的最大公约数是一个质数p&#xff0c;那么这两个数都除以p&#xff0c;得到的两个数的最大公约数一定是1. 反证法&#xff1a;如果得到的两个数的最大公约数不是1&#xff0c;那么把此时的最大公约数乘以上边的最大公约数&#xff0c;得到的一定比上…

Go语言工程实践之测试与Gin项目实践

Go 语言并发编程 及 进阶与依赖管理_软工菜鸡的博客-CSDN博客 03 测试 回归测试一般是QA(质量保证)同学手动通过终端回归一些固定的主流程场景 集成测试是对系统功能维度做测试验证,通过服务暴露的某个接口,进行自动化测试 而单元测试开发阶段&#xff0c;开发者对单独的函数…

C# int和uint类型学习

在C#中&#xff0c;使用int表示整数类型&#xff0c;对应于.NET的System.Int32结构&#xff1b; C#中的int类型占4字节(4*832位)内存空间&#xff0c;其范围从-2,147,483,648 到 2,147,483,647&#xff1b; int类型是默认的整数类型&#xff0c;并且默认值是0&#xff1b; u…

Oracle database 静默安装 oracle 11g 一键安装

基于oracle安装包中应答文件实现一键安装 支持环境&#xff1a; Linux &#xff1a;centerOS 7 oracle &#xff1a;11.2.0 Oracle应答文件 runInstaller应答文件 /database/response/db_install.rsp netca应答文件 /database/response/netca.rsp dbca应答文件 /database/re…

Redis数据结构——跳跃表

跳跃表 先来回顾常规的跳跃表。 &#xff01;&#xff01;&#xff01;下面的图片和内容都来自于这个链接Redis数据结构——跳跃表 - 随心所于 - 博客园 对于一个有序的链表&#xff0c;我们如何才能快速定位一个元素呢&#xff1f;只能遍历&#xff0c;时间复杂度是O(N)&…

【实操】2023年npm组件库的创建发布流程

2022年的实践为基础&#xff0c;2023年我再建一个组件库【ZUI】。步骤回顾&#xff1a; 2022年的npm组件包的发布删除教程_npm i ant-design/pro-components 怎么删除_啥咕啦呛的博客-CSDN博客 1.在gitee上创建一个项目,相信你是会的 2.创建初始化项目&#xff0c;看吧&#…

86. 分隔链表

86. 分隔链表 题目-中等难度示例1. 新建两链表&#xff0c;根据x值分类存放&#xff0c;最后合并 题目-中等难度 给你一个链表的头节点 head 和一个特定值 x &#xff0c;请你对链表进行分隔&#xff0c;使得所有 小于 x 的节点都出现在 大于或等于 x 的节点之前。 你应当 保…

帮助中心干货:7步即可在线搞定产品帮助中心!

在产品的生命周期中&#xff0c;帮助中心是一个非常重要的部分&#xff0c;它能够为用户提供必要的信息和解决方案&#xff0c;帮助他们更好地使用产品。如果你正在寻找一种简单高效的方法来在线搭建产品帮助中心&#xff0c;那么这篇干货文章将为你提供7个步骤&#xff0c;让你…

WebDAV之π-Disk·派盘+Commander One

Commander one是一款为Mac用户设计的双窗格文件管理器,Commander One专业版在原先的版本功能拥有较大的提升。Commander One PRO可以帮助大家将文件从一个地方复制到另一个地方,支持多标签浏览、搜索、自定义热键设置、显示隐藏文件等功能。 π-Disk派盘 – 知识管理专家 派…

[迁移学习]领域泛化

一、概念 相较于领域适应&#xff0c;领域泛化(Domain generalization)最显著的区别在于训练过程中不能访问测试集。 领域泛化的损失函数一般可以描述为以下形式&#xff1a; 该式分为三项&#xff1a;第一项表示各训练集权重的线性组合&#xff0c;其中π为使该项最小的系数&a…

Linux下在qtcreator中创建qt程序

目录 1、新建项目 2、单工程项目创建 3、多工程项目创建 4、添加子工程&#xff08;基于多工程目录结构&#xff09; 5、 .pro文件 1、新建项目 切换到“编辑”界面&#xff0c;点击菜单栏中的“文件”-“新建文件或项目” 2、单工程项目创建 只有一个工程的项目&#…

uniapp使用阿里矢量库

然后解压复制全部到你的项目文件 最后只要这几个 然后引入 最后在你需要的页面使用

电脑系统重装日记

重装原因 电脑C盘几乎爆炸故重装系统一清二白 此片原因 记录重装过程&#xff0c;强调一些要注意的点&#xff0c;以防日后重装。 重装过程 1.清空电脑文件后重启&#xff0c;电脑冒蓝光&#xff0c;一直蓝屏反复重启&#xff0c;故只能重装系统以解难题。 2.准备一个U盘&…

手机里视频太大怎么压缩?压缩教程分享

现在视频文件的体积越来越大了&#xff0c;动不动就是几个GB起步&#xff0c;如果后期再剪辑处理一下&#xff0c;更是会占据更多的设备空间了&#xff0c;还会导致我们传输受到限制&#xff0c;这时候就需要我们对视频进行压缩处理&#xff0c;下面给大家分享几个简单的方法&a…

生成式 AI 在泛娱乐行业的应用场景实践 – 助力风格化视频内容创作

感谢大家阅读《生成式 AI 行业解决方案指南》系列博客&#xff0c;全系列分为 4 篇&#xff0c;将为大家系统地介绍生成式 AI 解决方案指南及其在电商、游戏、泛娱乐行业中的典型场景及应用实践。目录如下&#xff1a; 《生成式 AI 行业解决方案指南与部署指南》《生成式 AI 在…

spark的使用

spark的使用 spark是一款分布式的计算框架&#xff0c;用于调度成百上千的服务器集群。 安装pyspark # os.environ[PYSPARK_PYTHON]解析器路径 pyspark_python配置解析器路径 import os os.environ[PYSPARK_PYTHON]"D:/dev/python/python3.11.4/python.exe"pip inst…

SQLyog中导入CSV文件入库到MySQL中

1.在数据库中新建一个表&#xff0c;设置列名&#xff08;与待导入文件一致&#xff09;&#xff0c;字段可以多出几个都可以 2.右键表名&#xff0c;导入- - >导入使用本地加载的CSV数据 选择使用加载本地CVS数据 3.指定好转义字符&#xff0c;将终止设置为,号(英文状态下…

SciencePub学术| 智能计量类重点SCIE征稿中

SciencePub学术 刊源推荐: 智能计量类重点SCIE征稿中&#xff01;信息如下&#xff0c;录满为止&#xff1a; 一、期刊概况&#xff1a; 智能计量类重点SCIE 【期刊简介】IF&#xff1a;2.0-2.5&#xff0c;JCR3区&#xff0c;中科院4区&#xff1b; 【版面类型】正刊&#…

多维时序 | MATLAB实现ZOA-CNN-BiGRU-Attention多变量时间序列预测

多维时序 | MATLAB实现ZOA-CNN-BiGRU-Attention多变量时间序列预测 目录 多维时序 | MATLAB实现ZOA-CNN-BiGRU-Attention多变量时间序列预测预测效果基本介绍模型描述程序设计参考资料 预测效果 基本介绍 1.Matlab基于ZOA-CNN-BiGRU-Attention斑马优化卷积双向门控循环单元网络…

【CSS】禁用元素鼠标事件(例如实现元素禁用效果)

文章目录 基本用法 基本用法 pointer-events 属性指定在什么情况下 (如果有) 某个特定的图形元素可以成为鼠标事件。实际运用中可以通过对auto 和none动态控制&#xff0c;来动态实现元素的禁用效果。 属性描述auto与pointer-events属性未指定时的表现效果相同&#xff0c;对…