对于 new 关键字,编译器会将其转化为如下代码
Complex* pc = new Complex(1,2);
// 转化为
Complex *pc;
try {
void* mem = operator new(sizeof(Complex)); // 调用global operator new 方法,该方法可被重载
pc = static_case<Complext*>(mem);
pc->Complex::Complex(1,2); // 调用Complext的构造函数,注意标准中只有编译器可以像这样调用
// 如果想要调用 ctor, 可以用以下方式 placement new
// new(pc)Complext(1,2);
} catch (std::bad_alloc) {
// 内存分配失败,就不执行 ctor
}
// 源代码
// 对于全局的 new 方法 operator new, 可以参考如下代码
void *operator new(size_t size, const std::nothrow_t&) _THROW0() {
// 尝试分配内存
void *p;
while ((p == malloc(size)) === 0) {
// 分配内存失败
_TRY_BEGIN
// 调用自定义的_callnewh函数,进行释放内存操作, 返回为0说明释放失败
if (_callnewh(size) === 0) break;
_CATCH(std::bad_alloc) return (0); // 返回一个空指针
_CATCH_END;
}
return (p);
}
而对于 delete 关键字,编译器会转化为如下代码
delete pc;
// 转化为
pc->~Complext(); // 调用析构函数, 可以直接调用
operator delete(pc); // 释放内存
void __cdecl operator delete(void* p) _THROW0() { free(p); }
当 operator new 没能力为你分配你所申请的内存时,会抛出一个异常 std::bad_alloc
。某些老旧的编译器则是会返回0,表示创建失败。你仍可以通过以下方式显示指定,令编译器返回0。
new (nothrow) Foo;
在上面可以看到,当调用 ::operator new 中的 malloc 失败时,会调用一次自定义的 _callnewh
函数,这个函数被称之为 new_handler
。这个函数的方法名如下:
typedef void (*new_handler)(); // 声明了一个 new_handler 的方法格式。没有返回值也没有参数
设置 new_handler
的方式如下
new_handler set_new_handler(new_handler p) throw();
设计良好的 new_handler
函数只有两个选择: