-
条款50已经解释了什么时候你需要写个自定义的 new 和 delete,但没有解释你编写时应该遵守什么样的规则,接下来我们将介绍其中的规则。
-
对于 operator new:
-
operator new 的返回值很简单。如果它有能力供应客户申请的内存,就返回一个指针指向那块内存。如果没那个能力,就遵循条款49描述的规则。
-
C++ 规定,即使客户要求 0 bytes,operator new也得返回一个合法指针。常用的做法是将 0 bytes 申请量视为 1 bytes 申请量。
-
operator new 内含一个无限循环,除非内存被成功分配或调用 new_handlers 时它们做了条款49描述的哪些事情:让更多内存可用,安装另一个 new_handler,卸除 new_handler,抛出 bad_alloc 异常,调用 abort() 或 exit()…否则 operator new 内的无限循环永远不会结束。
-
记住没有直接的方式取得 new-handler 函数指针,必须调用 set_new_handler 使用它的返回值。
-
许多人未意识到 operator new 成员函数会被 derived class 继承,而 operator new 是针对 base class 专门设计的内存分配函数,如果derived class 忘记重写该函数,会导致内存分配出错。简单的做法是令其调用标准版 operator new。
-
如果打算控制数组内存分配,就得实现 operator new[ ] 。唯一要做的一件事是分配一块原始内存(raw memory)。因为你无法对 array 内不存在的元素做任何事情。对于 base-derived 体系而言,通常来说 derived class 要比其 base class 大,使用 btyes/ sizeof(base) 计算不出 array 元素的实际个数。
此外,正如条款16所说,动态分配的 arrays 可能需要包含额外的空间用于存放元素的个数。
示例代码:
void* operator new(std::size_t Size) throw(std::bad_alloc) { if (Size != sizeof(Base)) { return ::operator new(Size); } while(true) { //...分配内存 if ("分配成功") { //...返回首指针 }else { //...条款49讲述的事情 } } } -
-
对于 operator delete:
-
C++ 保证删除 nullptr 指针永远安全。所以我们必须实现这样的保证。
-
对于 base-derived 体系,不要忘记重写 derived class 的 delete 函数或者调用标准版 operator delete。
注意,如果删除的对象派生自某个 base class 而后者缺少 virtual 析构函数,那么 C++ 传给 operator delete 的 size_t 数值可能不正确,导致析构行为异常,这也是条款7所强调的内容。
示例代码:
void operator delete(void* RawMemory, std::size_t Size) throw() { if (RawMemory == nullptr) { return; } if (Size != sizeof(Base)) { return ::operator new(Size); } //...释放内存 return; } -
- operator new 应该内含一个无穷循环,并在其中尝试分配内存,如果它无法满足内存需求,就该调用 new-handler。它也应该有能力处理 0 bytes 申请。 Class 专属版本则还应该处理比正确大小更大的(错误)申请。
- operator delete 应该在收到 nullptr 指针时不做任何事。Class 专属版本则还应该处理比正确大小更大的(错误)申请。



