如果不兼容(也就是说不能用系统默认的 ::operator delete(void*) 来释放内存),那么你得重载 ::operator delete(void*),让它的行为与你的 operator new(size_t size, const char* file, int line) 匹配。一旦你决定重载 ::operator delete(void*),那么你必须重载 ::operator new(size_t),这就回到了情况 1:你无权重载全局 ::operator new(size_t)。
如果选择兼容系统默认的 ::operator delete(void*),那么你在 operator new(size_t size, const char* file, int line) 里能做的事情非常有限,比方说你不能额外动态分配内存来做 house keeping 或保存统计数据(无论显示还是隐式),因为系统默认的 ::operator delete(void*) 不会释放你额外分配的内存。(这里隐式分配内存指的是往 std::map<> 这样的容器里添加元素。)
看到这里估计很多人已经晕了,但这还没完。
其次,在 library 里重载 operator new(size_t size, const char* file, int line) 还涉及到你的重载要不要暴露给 library 的使用者(其他 library 或主程序)。这里“暴露”有两层意思:1) 包含你的头文件的代码会不会用你重载的 ::operator new(),2) 重载之后的 ::operator new() 分配的内存能不能在你的 library 之外被安全地释放。如果不行,那么你是不是要暴露某个接口函数来让使用者安全地释放内存?或者返回 shared_ptr ,利用其“捕获”deleter 的特性?听上去好像挺复杂?这里就不一一展开讨论了,总之,作为 library 的作者,绝对不要动“重载 operator new()”的念头。
事实 2:在主程序里重载 ::operator new() 作用不大
这不是一条规则,而是我试图说明这么做没有多大意义。
如果用第一种方式重载全局 ::operator new(size_t),会影响本程序用到的所有 C++ library,这么做或许不会有什么问题,不过我建议你使用下一节介绍的更简单的“替代办法”。
如果用第二种方式重载 ::operator new(size_t size, const char* file, int line),那么你的行为是否惠及本程序用到的其他 C++ library 呢?比方说你要不要统计 C++ library 中的内存使用情况?如果某个 library 会返回它自己用 new 分配的内存和对象,让你用完之后自己释放,那么是否打算对错误释放内存做检查?
C++ library 从代码组织上有两种形式:1) 以头文件方式提供(如以 STL 和 Boost 为代表的模板库);2) 以头文件+二进制库文件方式提供(大多数非模板库以此方式发布)。
对于纯以头文件方式实现的 library,那么你可以在你的程序的每个 .cpp 文件的第一行包含重载 ::operator new 的头文件,这样程序里用到的其他 C++ l