条款50: 了解 new 和 delete 的合理替换时机
Understand when it makes sence to replace new and delete.首先怎么会有人想要替换编译器提供的 operator new 和 operator delete 呢?下面是三个最常见的理由:
1.用来检测运用上的错误.
如果自行定义一个 operator new,便可超额分配内存,以维阿空间(位于客户所得区块之前或后)放置特定的byte patterns(即签名,signatures). operator delete 使得检查上述签名是否原封不动,若否就表示在分配区的某个生命时间点发生了overrun或underrun,这时候 operator delete 可以记录那个事实以及那个指针.
2.为了强化效能.
因为内存管理器为了满足各种要求,采取了中庸之道.因此它对每个人都是适度的号,但不是最佳表现.如果自定义一个 operator new 和 operator delete,则性能胜过默认的版本很多.
3.为了收集使用上的统计数据.
自定义 operator new 和 operator delete 可以收集到动态分配内存时的很多信息.(例如分配区块的大小分布如何,寿命如何等等)
观念上,写一个定制型 operator new 十分简单.例如下面是个快速发展得出的初阶段 global operator new,促进并协助检测"overrun"(写入点在分配区块尾端之后)或"underrun"(写入点在分配区块起点之前):
static const int signature = 0XDEADBEEF;
typedef unsigned char Byte;
void* operator new(std::size_t size) throw(std::bad_alloc) {
using namespace std;
size_t realSize = size + 2 * sizeof(int);
void* pMem = malloc(realSize);
if (!pMem)
throw bad_alloc();
// 将signature写入内存的最前段落和最后段落
*(static_cast<int*>(pMem)) = signature;
*(reinterpret_cast<int*>(static_cast<Byte*>(pMem)+realSize-sizeof(int))) = signature;
// 返回指针,指向恰位于第一个signature之后的内存位置
return static_cast<Byte*>(pMem) + sizeof(int);
}
本条款的主题是,了解何时可在"全局性的"或"class专属的"基础上合理替换缺省的 new 和 delete .在这之前,先对答案做一些摘要:
1.为了检测运用错误(如前所述)
2.为了收集动态分配内存的使用统计信息(如前所述)
3.为了增加分配和归还的速度
4.为了降低缺省内存管理器带来的空间额外开销
5.为了弥补缺省分配器中的非最佳齐位
6.为了将相关对象成簇集中
7.为了获得非传统的行为
注意:
有许多理由需要写个自定义的 new 和 delete,包括改善效能,对heap运用错误进行调试,收集heap使用信息.