[原创文章欢迎转载,但请保留作者信息]
Justin 于 2010-05-28
其实平时很多时候都会看到重载new和delete的情况,不过应该没有很全面的归纳过为什么要这么做。于是大师来做了这件事:
- 重载new和delete的一个原因是可以在分配的内存块前加上特定的信息(如内存ID号),到释放的时候delete检查将要释放的内存是否符合释放的条件(如是否已经释放过了一次;是否大小与申请时不吻合;是否有权释放,等等)。曾经工作过的公司就有这样重载new和delete的方法,组里某牛还曾在每块内存前面加上一段分配内存时的堆栈内容,于是解决了许多豪无头绪的内存泄漏问题。
- 对这对操作符的重载通常可以提高效率。默认的new和delete的目标是通用,它们需要考虑到所有可能的内存分配/释放情况,就需要为这些林林总总的情况实现应对的代码。于是
- 额外的代码用于保证多线程安全,
- 额外的空间用于跟踪内存分配,
- 对是否需要地址对齐的不确定导致可能的效率下降,
- 由于目标系统的不明确,一些可以绑定在一起分配的数据没办法做到,
- 由于目标系统的不明确,一些特定的需求(比如说将释放的内存块全部写0)无法实现,
于是就变成一个任何人都可以用,但没有一个人会认为是最好用的new+delete。重载new和delete,可以剔除那些对自己无用的处理机制,保留甚至加强自己需要的功能,于是就提高了内存分配/释放的效率。当然,可以这样做的前提就是对自己的系统很了解。
- 用重载的new和delete来收集系统内存使用数据。在真正设计内存相关行为之前,可以借由重载的new和delete来收集各类数据,因为它们是目击每次内存分配和释放的证人。
不过,虽然重载new和delete有以上诸多好处,大师还是建议:如非必需,还是不要自己写new/delete这样的内存管理程序。因为要写这样的程序不难,要写好就不容易。
上课的时候大师举了个比较常见的例子,就是在重载new时,如果没有考虑到内存地址对齐(alignment)的问题,写出来的程序就有可能崩溃,或者,至少会跑得比较慢。
所以,在想要重载new和delete的时候,先看看是不是已经有下面的更简单安全有效的选项:
- 编译器有开关可以提供需要的功能,如调试/内存日志等,没有必要自己做
- 很多商用平台已经提供了成熟的new和delete可以重载,只要你买了(或是你的公司买了),就可以直接来用。
- 再有就是有很多开源的内存管理工具可以借用。大师推荐Boost的Pool Library就是其中之一。