【C++基础(九)】C++内存管理--new一个对象出来

💓博主CSDN主页:杭电码农-NEO💓

⏩专栏分类:C++从入门到精通⏪

🚚代码仓库:NEO的学习日记🚚

🌹关注我🫵带你学习C++
  🔝🔝


在这里插入图片描述

C++内存管理

  • 1. 前言
  • 2. new
    • 2.1 new的使用方法
    • 2.2 new的特性(对比malloc)
  • 3. delete
    • 3.1 delete的使用方法
    • 3.2 delete的特性(对比free)
  • 4. 全局函数operator new
  • 5. 全局函数operator delete
  • 6. new的实现原理
  • 7. delete的实现原理
  • 8. 总结以及拓展

1. 前言

在C语言中,有四个内存管理函数:
malloc,calloc,realloc和free

但是它们的使用十分的不方便:

int* p=(int*)malloc(sizeof(int)*n);

代码量很大,并且有一个新的问题:

malloc函数不会初始化变量
当变量是自定义类型的时候
C语言的内存管理函数无法
自动调用变量的构造/析构函数!

于是C++祖师爷发话了:
C++要自己搞一个内存管理!

在这里插入图片描述


2. new

2.1 new的使用方法

new的使用方法:

  1. 开辟多个空间
int* p = new int[100];

这段代码可以这样理解:

在这里插入图片描述


  1. 开辟一个空间并初始化
class A
{
public:A(int a = 0): _a(a){}
private:int _a;
};A* p = new A(10);

使用小括号()
这段代码初始化了一个对象成10
并且将地址赋值给指针变量p


  1. 开辟多个空间并初始化
A* p = new A[5]{1,2,3};

这段代码可以这样理解:

在这里插入图片描述


2.2 new的特性(对比malloc)

new的特性:

  • 对于内置类型来说,new和malloc
    并没有太大的区别

  • 对于自定义类型来说,new会调用
    自定义类型的构造函数,而malloc不会

  • new可以初始化变量的内容


3. delete

delete对比C语言中的free
是用来使用同台开辟的空间的/1

3.1 delete的使用方法

delete的使用:

  1. 直接使用delete
int* p = new int(10);
//使用指针p
delete p;

当new堆区空间时只开辟了一份空间
释放空间时直接使用delete即可

  1. 使用delete[]
int* p = new int[10]{1,2,3,4};
//使用指针p
delete[] p;

当new使用方括号[]开辟多个空间时
delete也要对应的加上[]来释放空间
否则会出错


3.2 delete的特性(对比free)

delete特性:

  • 对于内置类型,delete和free没有区别

  • 对于自定义类型,delete会调用
    自定义类型的析构函数,而free不会

  • delete面对不同的情况需要加上[ ]
    然而free不用考虑

对于自定义类型来说
有可能类中有指针指向一块堆区
如果不调用析构函数释放这块空间
直接用free释放掉对象的空间
那么这块空间就会内存泄漏!


4. 全局函数operator new

不同于C语言的malloc和free函数
new和delete是两个操作符
那new是怎样开辟空间的呢?

new在底层调用了operator new

注:
operator new是全局函数
不是运算符重载

库中的operator new函数:

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

可以发现,new的底层实际上是
使用了malloc来实现开辟空间

开辟空间成功,会返回指向此空间的指针
开辟空间失败,会抛异常

抛异常不是本节课的重点
它是C++一个全新的知识
在后面的章节会详细介绍
一般情况下,new申请空间都不会失败!


5. 全局函数operator delete

和new对应的delete的底层
也是调用了operator delete来
释放堆区开辟的空间

库中的operator delete函数:

#define free(p) _free_dbg(p, _NORMAL_BLOCK)
void operator delete(void *pUserData)
{_CrtMemBlockHeader * pHead;RTCCALLBACK(_RTC_Free_hook, (pUserData, 0));if (pUserData == NULL)return;_mlock(_HEAP_LOCK);__TRYpHead = pHdr(pUserData);_ASSERTE(_BLOCK_TYPE_IS_VALID(pHead->nBlockUse));_free_dbg( pUserData, pHead->nBlockUse );__FINALLY_munlock(_HEAP_LOCK);__END_TRY_FINALLYreturn;
}

看不懂没关系,只需要抓住重点:
delete里面调用了:
_free_dbg(p, _NORMAL_BLOCK)
然而此函数正是free函数定义的宏替换!

说明delete的底层实现实际上
是调用了C语言中的free函数

delete是使用free来释放空间的


6. new的实现原理

对于内置类型来说,new和
malloc的实现是一样的

对于自定义类型来说

  • new的原理步骤
  1. 调用operator new函数申请空间
  2. 在申请的空间上执行构造函数
    完成对象的构造
  • new T[N]的原理步骤
  1. 调用operator new[]函数
    完成N个对象空间的申请
  2. 在申请的空间上执行N次构造函数

7. delete的实现原理

对于内置类型来说,delete
和free的实现是一样的

对于自定义类型来说

  • delete的原理步骤
  1. 在空间上执行析构函数
    完成对象中资源的清理工作
  2. 调用operator delete函数释放对象的空间
  • delete[]的原理步骤
  1. 在释放的对象空间上执行N次析构函数
    完成N个对象中资源的清理
  2. 调用operator delete[]释放空间

8. 总结以及拓展

此章总结完,就可以去new一个对象了
并且C++和C语言中的内存管理区别
是面试中的常考点,和指针与引用的区别
俗称"面试山上的看门二虎"

下面就来总结一下:

  1. malloc和free是函数,new和delete是操作符
  1. malloc申请的空间不会初始化,new可以初始化
  1. malloc申请空间时,需要手动计算空间大小并传递,new只需在其后跟上空间的类型即可,如果是多个对象,[]中指定对象个数即可
  1. malloc的返回值为void, 在使用时必须强转,new不需要,因为new后跟的是空间的类型*
  1. malloc申请空间失败时,返回的是NULL,因此使用时必须判空,new不需要,但是new需要捕获异常
  1. 申请自定义类型对象时,malloc/free只会开辟空间,不会调用构造函数与析构函数,而new在申请空间后会调用构造函数完成对象的初始化,delete在释放空间前会调用析构函数完成空间中资源的清理

拓展:内存泄漏

内存泄漏指因为疏忽或错误造成程序未能释放已经不再使用的内存的情况。内存泄漏并不是指内存在物理上的消失,而是应用程序分配某段内存后,因为设计错误,失去了对该段内存的控制,因而造成了内存的浪费

更多关于内存泄漏的内容:
内存泄漏介绍
内存泄漏原因
内存泄漏检测方法
内存泄漏检测工具

可以参考这两篇文章:

内存泄漏百度百科
内存泄漏分类


🔎 下期预告:C++模板初阶讲解 🔍

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

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

相关文章

MIT 6.830数据库系统 -- lab six

MIT 6.830数据库系统 -- lab six 项目拉取引言steal/no-force策略redo log与undo log日志格式和检查点 开始回滚练习1:LogFile.rollback() 恢复练习2:LogFile.recover() 测试结果疑问点分析 项目拉取 原项目使用ant进行项目构建,我已经更改为…

Nodejs安装及环境变量配置(修改全局安装依赖工具包和缓存文件夹及npm镜像源)

本机环境:win11家庭中文版 一、官网下载 二、安装 三、查看nodejs及npm版本号 1、查看node版本号 node -v 2、查看NPM版本号(安装nodejs时已自动安装npm) npm -v 四、配置npm全局下载工具包和缓存目录 1、查看安装目录 在本目录下创建no…

【学习日记】【FreeRTOS】手动任务切换详解

前言 本文是关于 FreeRTOS 中实现两个任务轮流切换并执行的代码详解。目前不支持优先级,仅实现两个任务轮流切换。 一、任务的自传 任务从生到死的过程究竟是怎么样的呢?(其实也没死),这个问题一直困扰着我&#xf…

【前端 | CSS】滚动到底部加载,滚动监听、懒加载

背景 在日常开发过程中,我们会遇到图片懒加载的功能,基本原理是,滚动条滚动到底部后再次获取数据进行渲染。 那怎么判断滚动条是否滚动到底部呢?滚动条滚动到底部触发时间的时机和方法又该怎样定义? 针对以上问题我…

关于技术转管理角色的认知

软件质量保障:所寫即所思|一个阿里质量人对测试的所感所悟。 程序员发展的岔路口 技术人做了几年专业工作之后,会来到一个重要的“分岔路口”,一边是专业的技术路线,一边是技术团队的管理路线。不少人就开始犯难&…

redis 数据结构(一)

Redis 为什么那么快 redis是一种内存数据库,所有的操作都是在内存中进行的,还有一种重要原因是:它的数据结构的设计对数据进行增删查改操作很高效。 redis的数据结构是什么 redis数据结构是对redis键值对值的数据类型的底层的实现&#xff0c…

网站SSL安全证书是什么及其重要性

网站SSL安全证书具体来说是一个数字文件,是由受信任的数字证书颁发机构(CA机构)进行审核颁发的,其中包含CA发布的信息,该信息表明该网站已使用加密连接进行了安全保护。 网站SSL安全证书也被称为SSL证书、https证书和…

CosmosAI欧盟数字超算新时代战略合作签约仪式在伦敦举行

据英国权威媒体获悉,由分布式超算网络服务商CosmosAI主办的欧盟数字超算新时代战略合作签约仪式将于8月14日英国伦敦历史悠久的莱福士OWO酒店隆重举办,该酒店曾作为爱德华七世国王加冕仪式以及丘吉尔二战办公室享誉盛名。 本次活动CosmosAI基金会联合创…

护网专题简单介绍

护网专题简单介绍 一、护网红蓝队介绍1.1、网络安全大事件1.2、护网行动由来1.3、护网行动中的角色二、红队介绍2.1、红队所需技能2.2、红队攻击流程 三、蓝队介绍3.1、蓝队所需技能3.2、蓝队防守四阶段3.3、蓝队前期准备 四、常见安全厂商介绍4.1、常见安全厂商 五、常见安全产…

【vue3】基础知识点-pinia

学习vue3,都会从基础知识点学起。了解setup函数,ref,recative,watch、computed、pinia等如何使用 今天说vue3组合式api,pinia 戳这里,跳转pinia中文文档 官网的基础示例中提供了三种写法 1、选择式api&a…

树莓派命令行运行调用音频文件的函数,不报错,没有声音解决办法

树莓派接上音频首先需要切换音频不是HDMI,然后可以双击运行wav文件可以播放,但是: 命令行直接运行wav文件报错: Playing WAVE twzc.wav : Signed 16 bit Little Endian, Rate 16000 Hz, Mono命令行运行main方法也是无法播放&am…

Zebec Protocol 将进军尼泊尔市场,通过 Zebec Card 推动地区金融平等

流支付正在成为一种全新的支付形态,Zebec Protocol 作为流支付的主要推崇者,正在积极的推动该支付方案向更广泛的应用场景拓展。目前,Zebec Protocol 成功的将流支付应用在薪酬支付领域,并通过收购 WageLink 将其纳入旗下&#xf…

消息中间件 —— 初识Kafka

文章目录 1、Kafka简介1.1、消息队列1.1.1、为什么要有消息队列?1.1.2、消息队列1.1.3、消息队列的分类1.1.4、p2p 和 发布订阅MQ的比较1.1.5、消息系统的使用场景1.1.6、常见的消息系统 1.2、Kafka简介1.2.1、简介1.2.2、设计目标1.2.3、kafka核心的概念 2、Kafka的…

git 报错 protocol ‘https‘ is not supported解决

报错原因:选择不了其他分支代码,甚至都看不到其他分支,我这边解决了两次报错,情况如下: 第一种报错: idea中刷新分支报错如下: Fetch Failed protocol https is not supported 话不多说&#…

有没有推荐的golang的练手项目?

前言 下面是github上的golang项目,适合练手,可以自己选择一些项目去练习,整理不易,希望能多多点赞收藏一下!废话少说,我们直接进入正题>>> 先推荐几个教程性质的项目(用于新手学习、巩…

Qt在mac安装

先在app store下载好Xcode 打开Xcode 随便建个文件 给它取个名字 找个地方放 提醒没建立git link,不用理他 打开终端, 输入/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" 开始安装啦 继续在终端…

【Uni-App】uview 开发多端应用,密码显示隐藏功能不生效问题

出现的问题: 使用uview组件u-input框密码绑定时会出现右侧密码显隐图标不显示的问题 思路: 1.看了下uview源码,发现这有一段注释,我们需要把源码修改一下,问题出在这里 这行代码修改为 :password"password || …

山东布谷科技直播系统源码热点分析:不同芯片实现高质量编码与渲染视频的GPU加速功能

在现代科技的迅猛发展下,直播系统源码平台被开发搭建出来,为人们的生活方式带来了很大的改变,直播系统源码平台的好友、短视频、直播、社区等功能让很多人越来越热衷于去在平台上刷视频、看直播、分享生活。用户的喜爱也督促了直播系统源码平…

【数据结构与算法】十大经典排序算法-快速排序

🌟个人博客:www.hellocode.top 🏰Java知识导航:Java-Navigate 🔥CSDN:HelloCode. 🌞知乎:HelloCode 🌴掘金:HelloCode ⚡如有问题,欢迎指正&#…

中国钢铁工业协会 :2022年钢铁行业经济运行报告(附下载)

关于报告的所有内容,公众【营销人星球】获取下载查看 核心观点 2022年,我国粗钢产量10.18亿吨,比上年下降1.7%,连续两年下降,降幅比上年收窄。2022年,出口钢材 6732万吃,比上年增长0.9%;进口钢…