“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++
中,malloc
和new
都用于在堆上分配内存,但有一些重要的区别。
-
语法和类型安全性:
malloc
和free
是函数,new
和delete
是操作符
(1)malloc
是C语言中的函数,malloc
需要指定要分配的内存大小,并返回一个指向未初始化内存块的指针。
(2)new
是C++
中的运算符。new
可以直接在创建对象时进行初始化,并返回一个指向已经构造的对象的指针。new
操作符会执行类型检查,确保分配的内存与对象类型匹配。 -
构造函数和析构函数调用:
(1)使用new
分配内存时,会自动调用对象的构造函数进行初始化。
(2)使用malloc
分配内存时,不会调用对象的构造函数,需要手动调用构造函数初始化对象。
(3)同样,使用delete
释放new
分配的内存时,会自动调用析构函数进行清理工作。而使用free
释放malloc
分配的内存时,不会自动调用析构函数,需要手动执行清理操作。 -
内存大小计算:
(1)使用malloc
分配内存时,需要显式指定要分配的内存块的大小,以字节为单位。
(2)使用new
分配单个对象时,编译器会自动计算所需的内存大小,以对象的类型为基础。对于数组对象,需要使用new[]
和delete[]
,同样会自动计算所需的内存。 -
异常处理:
new
在分配内存失败时,会抛出std::bad_alloc
异常,而malloc
在分配内存失败时,返回NULL
指针。 -
malloc
的返回值为void*
, 在使用时必须强转,new
不需要,因为new
后跟的是空间的类型
总的来说,new
相对于malloc
提供了更高级的、更安全的内存分配方式,能够自动调用构造函数和析构函数,执行类型检查,并提供异常处理。因此,在C++
中,推荐使用new
和delete
来进行动态内存分配和释放。如果你需要使用C语言的库或与C代码进行交互,可以使用malloc
和free
。
三、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 new
和operator 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
操作符的相关知识就讲到这里了,希望对大家有所帮助.
如果觉得文章有帮助的话,可以来个一键三连吗?
相关文章:

“new出对象“原理的深层解密
🎈个人主页:🎈 :✨✨✨初阶牛✨✨✨ 🐻推荐专栏1: 🍔🍟🌯C语言初阶 🐻推荐专栏2: 🍔🍟🌯C语言进阶 🔑个人信条: 🌵知行合一 …...
Java基础篇--SecureRandom(安全随机)类
java.security.SecureRandom类是Java中用于生成安全的随机数的一个类。与普通的Random类不同,它提供了一种可信赖的随机数生成器,用于生成具有高度随机性的随机数。 SecureRandom类的实例使用了更加安全的随机数生成算法,这些算法通常经过密…...

论文复现--关于多视角动作捕捉工具箱 --XRMoCap的研究
分类:动作捕捉 github地址:https://github.com/openxrlab/xrmocap 所需环境: Ubuntu18.04,conda22.9.0,CUDA11.4 目录 环境配置 环境配置 conda create -n XRmocap python3.7 -y conda activate XRmocap# install ffm…...

Spring Profile与PropertyPlaceholderConfigurer实现项目多环境配置切换
最近考虑项目在不同环境下配置的切换,使用profile注解搭配PropertyPlaceholderConfigurer实现对配置文件的切换,简单写了个demo记录下实现。 基本知识介绍 Profile Profile通过对bean进行修饰,来限定spring在bean管理时的初始化情况&#…...

ansible入门
ansible入门 一.ansible 背景介绍 Ansible 是一个广受欢迎的 IT 自动化系统。可以用来处理配置管理、应用自动化部署、云资源配给、网络 自动化和多借点部署等任务。其也可以使得复杂的变更如带负载均衡的零停机滚动更新更加容易。Ansible.com 1.1 自动化运维概念 1.1.1 运维…...

用Node.js吭哧吭哧撸一个运动主页
简单唠唠 某乎问题:人这一生,应该养成哪些好习惯? 问题链接:https://www.zhihu.com/question/460674063 如果我来回答肯定会有定期运动的字眼。 平日里也有煅练的习惯,时间久了后一直想把运动数据公开,…...

【C++】STL---vector
STL---vector 一、vector 的介绍二、vector 的模拟实现1. 容量相关的接口(1)size(2)capacity(3)reserve(4)resize(5)empty 2. [] 重载3. 迭代器4. 修改数据相…...

机器学习:基本介绍
机器学习介绍 Hnad-crafted rules Hand-crafted rules,叫做人设定的规则。那假设今天要设计一个机器人,可以帮忙打开或关掉音乐,那做法可能是这样: 设立一条规则,就是写一段程序。如果输入的句子里面看到**“turn of…...
基于长短期神经网络LSTM的碳排量预测,基于LSTM的碳排放量预测
目录 背影 摘要 LSTM的基本定义 LSTM实现的步骤 基于长短期神经网络LSTM的碳排放量预测 完整代码: 基于长短期神经网络LSTM的碳排放量预测,基于LSTM的碳排放量预测资源-CSDN文库 https://download.csdn.net/download/abc991835105/88184632 效果图 结果分析 展望 参考论文 背…...

日常BUG——SpringBoot关于父子工程依赖问题
😜作 者:是江迪呀✒️本文关键词:日常BUG、BUG、问题分析☀️每日 一言 :存在错误说明你在进步! 一、问题描述 在父子工程A和B中。A依赖于B,但是A中却无法引入B中的依赖,具体出现的…...

Zabbix监控tomcat
文章目录 一、安装部署TomcatTomcat二、安装Tomcat1.安装zabbix-agent收集监控数据(192.168.40.104)2.安装部署Zabbix-server(192.168.40.105)3.配置数据库 三、Zabbix监控Tomcat页面设置 实验环境 主机用途Centos7:192.168.40.105zabbix-server,zabbix-java-gatew…...

CentOS-6.3安装MySQL集群
安装要求 安装环境:CentOS-6.3 安装方式:源码编译安装 软件名称:mysql-cluster-gpl-7.2.6-linux2.6-x86_64.tar.gz 下载地址:http://mysql.mirror.kangaroot.net/Downloads/ 软件安装位置:/usr/local/mysql 数据存放位…...

项目管理的艺术:掌握成本效益分析
引言 在项目管理中,我们经常面临着如何有效地使用有限的资源来实现项目目标的挑战。为了解决这个问题,我们需要使用一种强大的工具——成本效益分析。通过成本效益分析,我们可以评估和比较不同的项目选项,选择最具成本效益的项目…...

护眼灯值不值得买?什么护眼灯对眼睛好
想要选好护眼台灯首先我们要知道什么是护眼台灯,大的方向来看,护眼台灯就是可以保护视力的台灯,深入些讲就是具备让灯发出接近自然光特性的光线,同时光线不会伤害人眼而出现造成眼部不适甚至是视力降低的照明设备。 从细节上看就…...

【设备树笔记整理4】内核对设备树的处理
1 从源头分析_内核head.S对dtb的简单处理 1.1 bootloader向内核传递的参数 (1)bootloader启动内核时,会设置r0,r1,r2三个寄存器: r0一般设置为0;r1一般设置为machine_id (在使用设备树时该参数没有被使用…...

算法通关村第七关——递归和迭代实现二叉树前中后序遍历
1.递归 1.1 熟悉递归 所有的递归有两个基本特征: 执行时范围不断缩小,这样才能触底反弹。终止判断在调用递归的前面。 写递归的步骤: 从小到大递推。分情况讨论,明确结束条件。组合出完整方法。想验证就从大到小画图推演。 …...

Datawhale Django后端开发入门Task01 Vscode配置环境
首先呢放一张运行成功的截图纪念一下,感谢众多小伙伴的帮助呀,之前没有配置这方面的经验 ,但还是一步一步配置成功了,所以在此以一个纯小白的经验分享如何配置成功。 1.选择要建立项目的文件夹,打开文件找到目标文件夹…...
django部署到centos服务器上
具体的操作步骤 步骤一 更新系统和安装依赖, sudo yum update sudo yum install python3 python3-pip python3-devel git步骤二:创建并激活虚拟环境 在终端中执行以下命令: python3 -m venv myenv source myenv/bin/activate可以不创建虚拟…...

IOS开发-XCode14介绍与入门
IOS开发-XCode14介绍与入门 1. XCODE14的小吐槽2. XCODE的功能bar一览3. XCODE项目配置一览4. XCODE更改DEBUG/RELEASE模式5. XCODE单元测试 1. XCODE14的小吐槽 iOS开发工具一直有个毛病,就是新版本的开发工具的总会有一些奇奇怪怪的bug。比如在我的Mac-Pro&#…...
Interactive Marker Publish Pose All the Time (Interactive Marker通过topic一直发送其状态)
以下代码实现了:Interactive Marker通过topic一直发送其状态,而不只是交互时才发送。 几个要点: 通过定时器rospy.Timer实现PublishInteractiveMarkerServer feedback.pose的类型是geometry_msgs/Pose,而不是geometry_msgs/PoseS…...
java 实现excel文件转pdf | 无水印 | 无限制
文章目录 目录 文章目录 前言 1.项目远程仓库配置 2.pom文件引入相关依赖 3.代码破解 二、Excel转PDF 1.代码实现 2.Aspose.License.xml 授权文件 总结 前言 java处理excel转pdf一直没找到什么好用的免费jar包工具,自己手写的难度,恐怕高级程序员花费一年的事件,也…...

ESP32读取DHT11温湿度数据
芯片:ESP32 环境:Arduino 一、安装DHT11传感器库 红框的库,别安装错了 二、代码 注意,DATA口要连接在D15上 #include "DHT.h" // 包含DHT库#define DHTPIN 15 // 定义DHT11数据引脚连接到ESP32的GPIO15 #define D…...

el-switch文字内置
el-switch文字内置 效果 vue <div style"color:#ffffff;font-size:14px;float:left;margin-bottom:5px;margin-right:5px;">自动加载</div> <el-switch v-model"value" active-color"#3E99FB" inactive-color"#DCDFE6"…...
postgresql|数据库|只读用户的创建和删除(备忘)
CREATE USER read_only WITH PASSWORD 密码 -- 连接到xxx数据库 \c xxx -- 授予对xxx数据库的只读权限 GRANT CONNECT ON DATABASE xxx TO read_only; GRANT USAGE ON SCHEMA public TO read_only; GRANT SELECT ON ALL TABLES IN SCHEMA public TO read_only; GRANT EXECUTE O…...
Matlab | matlab常用命令总结
常用命令 一、 基础操作与环境二、 矩阵与数组操作(核心)三、 绘图与可视化四、 编程与控制流五、 符号计算 (Symbolic Math Toolbox)六、 文件与数据 I/O七、 常用函数类别重要提示这是一份 MATLAB 常用命令和功能的总结,涵盖了基础操作、矩阵运算、绘图、编程和文件处理等…...

自然语言处理——Transformer
自然语言处理——Transformer 自注意力机制多头注意力机制Transformer 虽然循环神经网络可以对具有序列特性的数据非常有效,它能挖掘数据中的时序信息以及语义信息,但是它有一个很大的缺陷——很难并行化。 我们可以考虑用CNN来替代RNN,但是…...

深入解析C++中的extern关键字:跨文件共享变量与函数的终极指南
🚀 C extern 关键字深度解析:跨文件编程的终极指南 📅 更新时间:2025年6月5日 🏷️ 标签:C | extern关键字 | 多文件编程 | 链接与声明 | 现代C 文章目录 前言🔥一、extern 是什么?&…...

多模态大语言模型arxiv论文略读(108)
CROME: Cross-Modal Adapters for Efficient Multimodal LLM ➡️ 论文标题:CROME: Cross-Modal Adapters for Efficient Multimodal LLM ➡️ 论文作者:Sayna Ebrahimi, Sercan O. Arik, Tejas Nama, Tomas Pfister ➡️ 研究机构: Google Cloud AI Re…...

初学 pytest 记录
安装 pip install pytest用例可以是函数也可以是类中的方法 def test_func():print()class TestAdd: # def __init__(self): 在 pytest 中不可以使用__init__方法 # self.cc 12345 pytest.mark.api def test_str(self):res add(1, 2)assert res 12def test_int(self):r…...
Angular微前端架构:Module Federation + ngx-build-plus (Webpack)
以下是一个完整的 Angular 微前端示例,其中使用的是 Module Federation 和 npx-build-plus 实现了主应用(Shell)与子应用(Remote)的集成。 🛠️ 项目结构 angular-mf/ ├── shell-app/ # 主应用&…...