新闻详情

新闻详情

首页 / 资讯中心 / 详情

C++入门到精通:内存管理全方位解析

发布时间:2026/10/2 12:44:59来源:尧图网络
C++入门到精通:内存管理全方位解析
前言本篇文章将带你了解new和delete运算符以及它们的实现原理。那么话不多说直接开始吧。C语言动态内存管理方式在了解C的new和delete之前我们先来说一下C语言的动态内存管理方式C中动态申请内存是在堆上申请有三个函数实现malloccallocrealloc。void*malloc(size_tsize);//size为总字节数void*calloc(size_tnmemb,size_tsize);//nmemb为个数size为单个元素字节大小void*realloc(void*ptr,size_tsize);//扩容size为总字节数void*malloc(sizeof(类型*个数;void*calloc(个数sizeof(类型;void*realloc(指针sizeof(类型)*个数;这三个虽都是动态申请但是有点差异三个都是申请完后返回这块要来的内存的首地址malloc里面是随机值不会初始化但是calloc会全部自动初始化为0。realloc的话一般是扩容它会先在原来已经申请好的空间后面尝试扩大空间扩容成功后返回地址后面扩容的地方不会初始化若是在之前申请好的地方后面空间不够它就会重新找一块足够的空间申请申请成功后将原来空间中的内容复制到新空间中之后释放掉旧空间返回新空间的地址扩容部分不初始化。我们来看段代码voidTest(){// 1.malloc/calloc/realloc的区别是什么int*p2(int*)calloc(4,sizeof(int));int*p3(int*)realloc(p2,sizeof(int)*10);//.........// 这里需要free(p2)吗free(p3);}这里是不需要freep2的若p2后空间够那么返回的还是p2的就地址p3和p2共用同一块空间所以p3释放一次就够了若p2后空间不够扩容成功返回新地址realloc自动释放了p2的旧空间所以无论怎样都不用再释放p2的旧空间了。C内存管理方式为什么在了解C内存管理方式之前要先了解C的呢因为new和delete是基于malloc和free再加上了一些其它的东西实现的以此来应对C中操作困难的地方我们来看下吧。new我们先来看下new的几种使用方式看下代码voidTest(){// 动态申请一个int类型的空间int*ptr4newint;//未初始化// 动态申请一个int类型的空间并初始化为10int*ptr5newint(10);int*ptr6newint{10};// 动态申请10个int类型的空间int*ptr7newint[3];//未初始化int*ptr8newint[3]{1,2,3};deleteptr4;deleteptr5;deleteptr6;delete[]ptr7;//数组必须这样删除delete[]ptr8;}类和对象版本MyClass*pnewMyClass();// 调用默认构造函数MyClass*p2newMyClass(1,2);// 调用带参构造函数deletep;deletep2;对于new和delete要配套使用用new就用delete用new[ ],就用delete[ ]申请和释放单个元素的空间使用new和delete操作符申请和释放连续的空间使用new[]和delete[]。接下来看下new和delete的实现原理吧。new和delete的实现原理对于内置类型普通的new申请失败会抛异常就是std::bad_alloc这种而nothrow 版本的new失败时返回 nullptr。对于malloc来说会返回空。其它地方对于内置类型来说new/delete和malloc/free几乎是一样的对于自定义类型对于自定义类型来说malloc申请会很麻烦所以一般都是用new并且new/delete和malloc/free的最大区别就在于对于自定义类型来说new会自动调用构造delete会自动调用析构函数malloc和free不会这也是malloc对于自定义类型处理起来很麻烦的点。自定义类型new处理方式调用operator new函数申请空间在申请的空间上执行构造函数完成对象的构造delete处理方式1.调用析构函数清理对象内部资源2.调用operator delete释放堆内存new T[N]处理方式调用operator new[]函数在operator new[]中实际调用operator new函数完成N个对象空间的申请在申请的空间上执行N次构造函数delete[]的原理在释放的对象空间上执行N次析构函数完成N个对象中资源的清理调用operator delete[]释放空间实际在operator delete[]中调用operator delete来释放空间对于delete的处理方式这里的析构函数和free做的并不是同一份工作我们来看段代码来搞懂classMyClass{int*data;// 指向堆上的数组public:MyClass(intn){datanewint[n];// 对象内部又申请了一块内存}~MyClass(){delete[]data;// 清理内部资源}};MyClass*pnewMyClass(10);deletep;1.调用析构函数 ~MyClass() → 释放 data 指向的那块数组内存2.调用 operator delete§ → 把 p 自己指向的那块 MyClass 对象内存还给堆如果只做第 1 步不做第 2 步p 指向的那块对象内存就泄漏了。如果只做第 2 步不做第 1 步data 指向的数组内存就泄漏了。所以这里调用析构函数只会清理该对象内部的资源而对象本身占有的资源需要用free来释放。用张表格更清楚的看到operator new和operator delete函数new和delete是用户进行动态内存申请和释放的操作符operator new 和operator delete是系统提供的全局函数new在底层调用operator new全局函数来申请空间delete在底层通过operator delete全局函数来释放空间。其实这两个函数在底层就是malloc和freeoperator new申请失败会先执行用户给的失败应对措施否则就抛异常就是上面讲解的。operator new底层void*__CRTDECLoperatornew(size_t size)_THROW1(_STD bad_alloc){// try to allocate size bytesvoid*p;while((pmalloc(size))0)if(_callnewh(size)0){// report no memory// 如果申请内存失败了这里会抛出bad_alloc 类型异常staticconststd::bad_alloc nomem;_RAISE(nomem);}return(p);}operator delete底层voidoperatordelete(void*pUserData){_CrtMemBlockHeader*pHead;RTCCALLBACK(_RTC_Free_hook,(pUserData,0));if(pUserDataNULL)return;_mlock(_HEAP_LOCK);/* block other threads */__TRY/* get a pointer to memory block header */pHeadpHdr(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;}这个底层我觉得可以不用看。#definefree(p)_free_dbg(p,_NORMAL_BLOCK)这个是MSVC CRT 提供的调试机制。是一个宏替换。它的含义是在预处理阶段把代码里写的 free§ 替换成 _free_dbg(p,_NORMAL_BLOCK)。_free_dbg 是 free 的 调试版本。_NORMAL_BLOCK 表示这块内存属于普通用户分配的内存块。#define_CRTDBG_MAP_ALLOC#includestdlib.h#includecrtdbg.h它需要这样一起使用。它只会在Debug模式下生效这样在 Debug 模式下malloc、free 会被映射到 _malloc_dbg、_free_dbgCRT 调试堆就能记录每次分配的文件名、行号、块类型并在程序退出时通过 _CrtDumpMemoryLeaks() 报告内存泄漏。总结malloc/free和new/delete的共同点是都是从堆上申请空间并且需要用户手动释放。不同的地方是malloc和free是函数new和delete是操作符malloc申请的空间不会初始化new可以初始化malloc申请空间时需要手动计算空间大小并传递new只需在其后跟上空间的类型即可如果是多个对象[]中指定对象个数即可malloc的返回值为void*, 在使用时必须强转new不需要因为new后跟的是空间的类型malloc申请空间失败时返回的是NULL因此使用时必须判空new不需要但是new需要捕获异常申请自定义类型对象时malloc/free只会开辟空间不会调用构造函数与析构函数而new在申请空间后会调用构造函数完成对象的初始化delete在释放空间前会调用析构函数完成空间中资源的清理释放.结束语到这里我们已经完整梳理了 C 语言与 C 在动态内存管理上的差异也深入剖析了 new 和 delete 从使用方式到底层实现的全过程。从 malloc/free 到 new/delete再到 operator new 与 operator delete 的底层逻辑相信你已经能清晰地理解new 和 delete 之所以更强大正是因为它们在 malloc 和 free 的基础上补上了构造与析构这两个关键环节让自定义类型的内存管理变得既安全又优雅。内存管理是 C/C 开发中绕不开的核心话题也是面试中高频考察的知识点。希望这篇文章能帮你把这块知识真正吃透在写代码时少踩几个内存泄漏的坑。如果你觉得内容对你有帮助欢迎点赞、收藏、转发也欢迎在评论区留言交流你的疑问或心得。我们下篇文章再见
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

C# sealed关键字深度解析:设计契约守护与工业级应用 2026/10/2 13:22:47

C# sealed关键字深度解析:设计契约守护与工业级应用

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
软件测试实战指南:接口、性能、APP与自动化四大技能详解 2026/10/2 13:22:34

软件测试实战指南:接口、性能、APP与自动化四大技能详解

干测试这一行的人应该都有体会,招聘要求翻来覆去就是那几样:接口测试、性能测试、APP测试、自动化测试。我在这个行业里泡了十年,从外包到自研、从金融领域到电商项目都接触过,踩坑无数,今天把那些真正能落地的测试实战…

阅读更多 →
56G PAM4 SerDes接收机BBCDR与DCO设计实践 2026/10/2 13:22:34

56G PAM4 SerDes接收机BBCDR与DCO设计实践

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
可复现的大数据实验报告:集群部署、MapReduce清洗与Hive分析 2026/10/2 13:22:34

可复现的大数据实验报告:集群部署、MapReduce清洗与Hive分析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
KGAT解析:知识图谱与图注意力网络驱动的推荐系统 2026/10/2 13:22:22

KGAT解析:知识图谱与图注意力网络驱动的推荐系统

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
嵌入式硬件RC/LC/RL滤波器设计避坑指南:从器件非理想性到PCB实现 2026/10/2 13:22:21

嵌入式硬件RC/LC/RL滤波器设计避坑指南:从器件非理想性到PCB实现

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉