C语言与C++内存分配:malloc、new用法及区别全解析
好多程序员在才开始触及接触C之际的时候老是被内存分配弄得晕头转向不知所措。new和malloc究竟到底有什么区别呢为何为什么C语言仅仅只能用malloc然而但C却又存在有好几种new呢弄不明白搞不清楚这些所编写写出来的代码随时就有可能会出现内存泄漏或者程序崩溃情况。new表达式与malloc的根本差异C语言不存在类的观念内存分配完全依靠malloc函数该函数仅仅是负责从堆区划分出一块连续的空间进而返回void指针。程序员获取到这块内存之后得要自己借助强制类型转换才行而且仅仅只能是通过赋值操作实现初始化。就好比int p (int)malloc(sizeof(int) * 10)这一行代码仅仅只是分配了40字节的空间其中里面的值是随机的。C所引入的new表达式是全然不一样的。当你写下int p new int(10)这样的语句的时候new表达式实施了两件事情其一它去调用operator new函数来分配充够的内存其二它调用int的构造函数将值设定为10。对于自定义的类型而言这种会自动调用构造函数的特性是极为关键重要的能够保证对象从起始之时就处于有效的状态防止出现未被初始化的成员变量的情况。定位new实现原地构造内存定位new属于new表达式的一种特别形式它让程序员能够在已分配好的内存之上构建对象。其典型用法是placement new语法为new(buffer) MyClass(args)。buffer需要指向一块足够大且对齐正确的内存区域这块内存有可能来自栈空间有可能来自全局区也有可能是借助malloc预先申请的堆内存。这项技术常常被运用在内存池、共享内存、嵌入式系统等场景之中。举例来说在游戏引擎里频繁地进行小对象的创建以及销毁操作预先去申请一大块内存每逢需要对象之际就借助定位new在指定的位置去进行构造从而避免了频繁地向系统申请释放内存所产生的开销。与定位new相对应的是显式地调用析构函数直接写成p-~MyClass()在此之后那块内存能够被重复利用并不需要进行释放。operator new与operator delete的底层机制不少人觉得new лишь有一种用法实则operator new乃是一个全局函数其仅仅负责内存划分作用近似于malloc。编译器默认供给了全局的operator new以及operator delete程序员能够对这些函数进行重载达成自定义的内存管控策略。比如说在嵌入式环境里能够重载operator new让其从特定的内存池中去分配空间。负责内存释放的是operator delete它不会调用析构函数。它跟delete表达式可不是一码事。delete表达式会先去调用对象的析构函数之后再调用由operator delete来释放内存。搞明白这个区分相当重要原因在于一旦程序对operator new进行了重载一般而言就需要配套地去重载operator delete不然的话分配和释放有可能出自不同机制进而造成内存错误。手动管理内存的典型错误与防范于C语言里运用malloc去分配内存后一旦忘却调用free那内存泄漏的情况便出现了。更进一步需留意更危险的情况也就是反复释放同一个内存块或者运用已经被释放后的野指针。此类错误在大型C项目当中尤其常见排查这类错误的时候便感到十分困难。在现代开发的过程里一般会建议针对每个malloc配套写上释放函数或者在函数出口之处统一进行释放。C即便给出了new以及delete然而同样是存有风险的。new表达式所分配的对象要是忘了去delete又或者delete数组的时候遗漏写方括号均会引发问题的。就好比用new分配了数组却使用delete而非delete[]去释放这会致使仅仅析构第一个元素其余元素的内存并未被释放。智能指针的引入在一定程度上解决了这些问题可是在底层代码或者性能敏感区域手动管理内存依旧是无法避免的。不同编译环境下的内存分配差异只能在纯C编译器里借助malloc系列函数去分配内存并且得手动计算字节数类型转换也是绝对不能少的。不过要是运用C编译器来编译C代码情形就变得繁杂起来了。好多C编译器准许在C代码之中使用new然而这并非标准C语言的行为移植性会受到影响的。堆内存管理机制于不同平台之下是存在差别的。Windows的堆管理器Linux的ptmalloc嵌入式系统的简化内存分配器在碎片处理方面在分配速度上面在多线程支持这一点上是各不相同的。当进行跨平台程序开发之时直接运用malloc或者new往往是无法满足所有平台的性能需求的需要借助内存池或者借助自定义分配器来统一行为以此确保在不同设备上表现一致。选择合适的内存分配方式在简单的C程序里malloc以及free便足以供使用之需将其与良好的编码习惯相配合能够撰写出稳定的代码。然而对于C项目而言应当优先去考量new表达式原因在于它更为安全并且能够自动调用构造函数。要是涉及到大量小对象频繁地进行创建以及销毁操作定位new联合内存池乃是更佳的选择它能够极大程度地减少内存碎片进而提升运行效率。在那种需要对对象构造位置加以控制的场景里头像是去实现容器又或是处理硬件映射内存再或者是运用共享进程间通信把那个定位new看作几乎是唯一的选择。而对于那些追求极致性能的这么个一系统对那operator new进行重载能够达成特定专门的这种内存分配上面的策略。得掌握这三种呈new的用法才可以在C内存管理这个范畴里能够做到游刃有余从而写出高效并且稳定的代码。在实际所涉及的项目当中你曾碰到过哪些是由于内存管理方面存在不恰当情况而引发的极为诡异的Bug呢欢迎于评论区域分享你自身所拥有的经历以及解决相应问题的思路。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2462312.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!