C++内存管理:new / delete 和 cookie
new 和 delete
C++的内存申请和释放是通过 new 和 delete 实现的, 而new 和 delete 其实就是通过 malloc 和 free 实现的。
new 申请内存分为三个步骤:
- 调用 operator new 函数分配目标类型的内存大小,operator new 函数内部就是调用的 malloc 函数。
- 将申请得到的内存块强制转换为目标类型指针。
- 通过指针调用目标的构造函数(只有编译器可以这样直接调用构造函数)。
delete 释放内存分为两个步骤:
- 调用对象的析构函数。
- 调用 operator delete 函数释放对象内存,operator delete 函数内部就是调用的 free 函数。
array new 和 array delete
array new 是申请多个对象的内存。
Cookie
通过 malloc 分配的内存,会在内存前后加上 cookie,以记录内存分配的总大小,这里以包含三个 int 数据的 Demo 类为例:
上面 61h 存储的就是内存块的大小,其中最低位用于表示是否已分配(1表示已分配,0表示已回收),其中的 3 记录了分配对象的数量。
当申请内存后,返回的指针指向数据开始处(00481c34),而使用 delete[] 释放时,指针会指向00481c30,从而可以根据对象的数量调用相应次数的析构函数。如果使用 delete 释放的话,它不会去00481c30地址获取对象的长度,而是直接释放00481c34位置处的对象。
所以,new[] 和 delete[] 需要配合使用,但是如果对象的类型是内置类型或者是无自定义的析构函数的类类型,是可以使用 delete 来释放 new[] 对象的。否则使用 delete 来释放对象的话,对象所分配的内存空间可以释放,但是只会调用第一个对象的析构函数,可能导致内存泄漏。
对于 cookie,可以从运行速度和空间使用两个方面去进行改进:
- 减少 malloc 的调用次数(虽然 malloc 的速度很快)。
- 每一个 new 的对象都会有上下两个 cookie,可以预先申请一块内存池,然后供对象实例化,这样只会在这一整块的内存池上下有 cookie,同时也可以减少 malloc 的调用次数。
(关于内存池可以看下一篇文章 C++内存管理:简易内存池的实现 )
参考:
如果您觉得阅读本文对您有帮助,请点一下“推荐”按钮,您的“推荐”将是我最大的写作动力!欢迎各位转载,但是未经作者本人同意,转载文章之后必须在文章页面明显位置给出作者和原文连接,否则保留追究法律责任的权利。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】Flutter适配HarmonyOS 5知识地图,实战解析+高频避坑指南
【推荐】凌霞软件回馈社区,携手博客园推出1Panel与Halo联合会员
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· C#多线程编程精要:从用户线程到线程池的效能进化论
· 如何反向绘制出 .NET程序 异步方法调用栈
· 领域驱动设计实战:聚合根设计与领域模型实现
· 突破Excel百万数据导出瓶颈:全链路优化实战指南
· 如何把ASP.NET Core WebApi打造成Mcp Server
· C#开发的Panel滚动分页控件 - 开源研究系列文章
· ShadowSql之开源不易
· 理解 C# 中的各类指针
· 如何反向绘制出 .NET程序 异步方法调用栈
· C#多线程编程精要:从用户线程到线程池的效能进化论
2016-12-13 UVa 10129单词(欧拉回路)