当前位置: 首页 > news >正文

C++?动态内存管理!!!

一、引言

        之前我们一起讨论了类和对象的相关知识,接下来我们将继续完善我们的知识体系,为以后继续深入学习C++知识添砖加瓦,在本期我们将一起学习C++中关于动态内存管理的相关知识,在学习之前将要先回顾C语言中是如何进行动态内存管理的。

二、内存中各个存储分区

        1、简介

        在内存中有很多不同的分区,比如栈区、堆区、静态区等,不同类型的数据被存储在分区里,不同的分区有不同的性质,方便管理。

        2、介绍

        内存中不同类型的数据在不同分区,如下图所示:
        

        (1).栈区中存储各种生命周期较短的数据---非静态局部变量、函数参数、函数返回值等,栈是向下增长的

        (2).内存映射段是高效的I/O映射方式,用于装载一个共享的动态内存库,用户可以使用系统接口创建共享内存,做进程间通信,在以后的操作系统相关会讨论到

        (3).堆区用于程序运行时进行动态内存分配,堆是向上增长的              

        (4).数据段,又叫静态区,存储生命周期与程序一样长的数据---全局数据和静态数据

        (5).代码段,又叫常量区,存储可执行的代码/常量

三、C语言的动态内存管理方式

        C语言主要通过malloc/calloc/realloc/free这几个函数进行对内存的申请与释放,它们的使用方式如下:
        

        可以看到:
                (1).malloc可以向内存中申请空间,需要传要开的空间大小,单位是字节,不会初始化内容

                (2).calloc与malloc类似,需要传要开几个大小为sizeofnum的空间,sizeofnum是第二个参数,会将所有内容初始化为0

                (3).realloc可以将之前开辟的空间扩容,传参时第一个参数传入之前动态开辟的指针,第二个参数是想开的空间大小,单位是字节

                (4).free用于释放动态开辟的空间,传入指针

                (5).以上用于开辟空间的函数返回值都是void*类型,需要进行强制类型转换

                (6).事实上还需要对开辟的空间成功与否进行检查,但由于这里只是回顾以下C语言的动态内存管理方式,所以不多赘述了

四、C++的动态内存管理方式

        1、引入

        C语言的动态内存管理方式对于内置类型来说是足够的,但是对于自定义类型就显得有一些吃力了,这是因为C语言的动态内存管理方式不能很好的对于初始化的对象进行初始化,在之前我们已经一起学习过C++类和对象相关的知识,对于自定义类型来说,是非常需要初始化的,也就是在定义时调用构造函数,怎么办呢?这时候就要使用到接下来要提到的C++动态内存管理方式---new和delete

        2、new和delete操作内置类型

        先看代码:
        

        new和delete对于内置类型的语法如上所示,接下来总结一下:
                (1).new之后跟一个类型表示向内存申请一块空间。如果是一个空间,可以在new后跟一个'()'对它进行初始化,'()'中的内容就是初始化的内容;在new后跟一个'[]'表示向内存申请多个空间,'[]'中就是要开辟该类型空间的个数,不能初始化

                (2).new会返回一个对应类型的指针,用户借助该指针对空间进行操作

                (3).如果开辟一个单位大小空间使用delete进行释放,如果是多个空间则使用delete[]进行释放,要匹配使用

        3、new和delete操作自定义类型

        在这里可以体会到malloc/free与new/delete的最大区别:new/delete会调用构造/析构函数,而malloc/free则不会,先看代码:
        

        由以上代码及其运行结果可以看出,new/delete会调用类的默认构造函数/默认析构函数,如果开辟多个空间,那么对于每一个对象都会调用一次,同时由p2也可以看出,在开辟空间的同时也可以传参调用构造函数,如果开辟多个空间同时没有默认构造函数怎么办呢?这时候可以象初始化数组一样使用‘{}’对该类对象数组进行初始化,代码如下:
                

        在上面演示了两种这种情况下的处理方式,分别是利用隐式类型转换和匿名类型,都可以选择

五、介绍operator new 和operator delete函数

        1、介绍

        new和delete是供用户使用的动态内存管理操作符,operator new 和operator delete则是两个库中实现的全局函数,new在底层调用operator new,delete在底层调用operator delete,这两个全局函数是由malloc和free封装而成的,主要进行的改动是将malloc申请内存失败时的返回NULL进行了封装,变为了抛异常,这是由于面向对象的语言更倾向于直接的抛异常,而不是通过返回值

        2、全局函数源码

 /*operator new:该函数实际通过malloc来申请空间,当malloc申请空间成功时直接返回;申请空间失败,
尝试执行空               
间不足应对措施,如果改应对措施用户设置了,则继续申请,否则抛异常。
*/void *__CRTDECL operator new(size_t size) _THROW1(_STD bad_alloc){// try to allocate size bytesvoid *p;while ((p = malloc(size)) == 0)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 );__FINALLY_munlock(_HEAP_LOCK);  /* release other threads */__END_TRY_FINALLYreturn;}   

        3、总结

        通过上述两个全局函数的实现知道,operator new 实际也是通过malloc来申请空间,如果malloc申请空间 成功就直接返回,否则执行用户提供的空间不足应对措施,如果用户提供该措施就继续申请,否则就抛异 常。operator delete 最终是通过free来释放空间的。                   

六、new和delete的实现原理

        1、对于内置类型

        对于内置类型new/new[]/malloc会开辟指定大小的空间,delete/delete[]/free会释放指定空间,不同的是new/new[]在申请失败时会抛异常,而malloc申请失败时会返回NULL

        2、对于自定义类型

                (1).new的原理

                        (1).1.调用operator new函数申请空间

                        (1).2.调用构造函数,对对象进行构造

                (2).delete的原理

                        (2).1.调用operator delete函数释放空间

                        (2).2.调用析构函数完成资源的清理

                (3).new T[N]的原理

                        (3).1.调用operator new[]函数,进而调用operator new函数完成N个函数空间的申请

                        (3).2.调用N次构造函数,完成N个对象的构造

                (4).delete[]的原理

                        (4).1.在目标空间的对象调用N次析构函数,完成N个对象的清理

                        (4).2.调用operator delete[]释放空间,进而调用operator delete对N个空间进行释放

六、对比malloc/free与new/delete

        malloc/free与new/deletw都是在堆上申请空间,它们的区别是:
                1、malloc和free是函数,new和deletw是操作符

                2、malloc申请的空间不会初始化,new可以初始化

                3、malloc要主动计算大小并对返回值进行强制类型转换,new只需要在后面加上类型名也不需要强转

                4、malloc申请空间失败时返回NULL而new申请失败时会抛异常

                5、在操作自定义类型时,malloc/free不会调用析构函数/构造函数,new和delete则会

七、结语

        这就是本期关于C++中动态内存管理相关的所有内容了,希望对大家有所帮助,感谢各位于晏、亦菲的阅读,欢迎大家和我一起讨论、进步。

相关文章:

  • Taro on Harmony :助力业务高效开发纯血鸿蒙应用
  • 【数据挖掘】时间序列预测-常用序列预测模型
  • I-CON: A Unifying Framework for Representation Learning
  • 23种设计模式-行为型模式之命令模式(Java版本)
  • 从零实现分布式WebSocket组件:设计模式深度实践指南
  • 【Linux网络与网络编程】13.五种 IO 模型
  • Zookeeper HA集群搭建
  • 使用vue2 开发一个纯静态的校园二手交易平台-前端项目练习
  • 区块链:去中心化应用(DApp)开发全流程解析
  • 全栈量子跃迁:当Shor算法破解RSA时,我们如何用晶格密码重构数字世界的信任基岩?
  • 计算机三大主流操作系统的前世今生 - Linux|macOS|Windows
  • 解锁现代生活的健康密码
  • 设计并实现一个基于 Java + Spring Boot + MySQL 的通用多租户权限系统
  • 榕壹云国际版短剧系统:基于Spring Boot+MySQL+UniApp的全球短剧创作平台
  • Golang | Builder模式
  • 神经网络(自己记录)
  • Java 设计模式心法之第25篇 - 中介者 (Mediator) - 用“中央协调”降低对象间耦合度
  • PDF嵌入隐藏的文字
  • Rule.resourceQuery(通过路径参数指定loader匹配规则)
  • PH热榜 | 2025-04-26
  • 绵阳造AI机器狗参与警务工作,演练中辅助民警控制“嫌疑人员”
  • 我国将出台稳就业稳经济推动高质量发展若干举措,将根据形势变化及时出台增量储备政策
  • 我的科学观|张峥:AI快速迭代,我们更需学会如何与科技共处
  • 王文涛会见德国汽车工业协会主席穆勒
  • “十四五”以来少数民族发展资金累计下达边疆省区252亿元
  • 杨荫凯已任浙江省委常委、组织部部长