Item 52 new/delete成对儿出现

● 通用概念
Widget *pw = new Widget;
其实分为两步:
1> 调用operator new分配内存
2> 调用ctor初始化对象

如果第2步抛出异常,系统会自动调用
1> void operator delete(void *mem) throw();
2> void Widget::operator delete(void *mem, std::size_t size) throw();
二者之一来回收内存。

系统查找和new对应的delete时是一一对应。如果对于一个placement new没有给出placement delete,则无法回收内存。
所以,自定义new/delete时要保持一一对应:

class Widget { public: static void* operator new(std::size_t size, std::ostream& log) throw(std::bad_alloc); static void operator delete(void *pMemory, std::ostream& log) throw(); ... }; Widget *pw = new (std::cerr) Widget;

 

此时若出现异常,系统会自动找到带ostream的delete。

● STL中有一个placement new:
void* operator new(std::size_t, void *pMemory) throw();
该函数用于vector在内部给新对象寻找存储位置。placement new因此而得名。placement是名词“安置、寻找合适位置”的意思。
现在一般意义上,只要带有多余参数的new都叫placement new。系统在匹配placement new和placement delete时,也是靠比较那些多余的参数而完成的。

● Item 33讲了类在派生的时候,如果重名就会发生定义遮挡的问题:

class Base { public: static void* operator new(std::size_t size, std::ostream& log) throw(std::bad_alloc); ... }; Base *pb = new Base; // 错误!默认的new被遮挡了 Base *pb = new (std::cerr) Base; // 正确 class Derived: public Base { public: // 这个厉害,把基类的也给挡了 static void* operator new(std::size_t size) throw(std::bad_alloc); ... }; Derived *pd = new (std::clog) Derived; // 错误 Derived *pd = new Derived; // OK

 

先要了解C++预定义的new:

void* operator new(std::size_t) throw(std::bad_alloc); // normal new void* operator new(std::size_t, void*) throw(); // placement new void* operator new(std::size_t, const std::nothrow_t&) throw(); // no-throw new

这些都是你要在你的类里重定义的。

简单做法如下:

class StandardNewDeleteForms { public: // normal new/delete static void* operator new(std::size_t size) throw(std::bad_alloc) { return ::operator new(size); } static void operator delete(void *pMemory) throw() { ::operator delete(pMemory); } // placement new/delete static void* operator new(std::size_t size, void *ptr) throw() { return ::operator new(size, ptr); } static void operator delete(void *pMemory, void *ptr) throw() { return ::operator delete(pMemory, ptr); } // nothrow new/delete static void* operator new(std::size_t size, const std::nothrow_t& nt) throw() { return ::operator new(size, nt); } static void operator delete(void *pMemory, const std::nothrow_t&) throw() { ::operator delete(pMemory); } }; // 谁想自定义new,就要从StandardNewDeleteForms里派生 class Widget: public StandardNewDeleteForms { public: // 然后用using声明一下标准的 using StandardNewDeleteForms::operator new; using StandardNewDeleteForms::operator delete; // 最后定义自己的 static void* operator new(std::size_t size, std::ostream& log) throw(std::bad_alloc); static void operator delete(void *pMemory, std::ostream& log) throw(); ... };

你可能感兴趣的:(Item 52 new/delete成对儿出现)