调用 global operator new 进行真正的内存分配。如果分配失败,global operator new 调用 Widget 的 new-handler,因为那个函数刚才被安装为 global new-handler。如果 global operator new 最后还是无法分配内存,它会抛出一个 bad_alloc exception。在此情况下,Widget 的 operator new 必须恢复原来的 global new-handler,然后传播那个 exception。为了确保原来的 new-handler 总能被恢复,Widget 将 global new-handler 作为一种资源对待,并遵循《C++箴言:使用对象管理资源》中的建议,使用 resource-managing objects(资源管理对象)来预防 resource leaks(资源泄漏)。
如果 global operator new 能够为一个 Widget object 分配足够的内存,Widget 的 operator new 返回一个指向被分配内存的指针。object 的用于管理 global new-handler 的 destructor(析构函数)自动将 global new-handler 恢复到调用 Widget 的 operator new 之前的状态。
以下就是你如何在 C++ 中表达这所有的事情。我们以 resource-handling class 开始,组成部分中除了基本的 RAII 操作(在构造过程中获得资源并在析构过程中释放)(《C++箴言:使用对象管理资源》),没有更多的东西:
class NewHandlerHolder { public: explicit NewHandlerHolder(std::new_handler nh) // acquire current :handler(nh) {} // new-handler
~NewHandlerHolder() // release it { std::set_new_handler(handler); } private: std::new_handler handler; // remember it
NewHandlerHolder(const NewHandlerHolder&); // prevent copying NewHandlerHolder& // (see 《C++箴言:谨慎考虑资源管理类的拷贝行为》) operator=(const NewHandlerHolder&); }; | 这使得 Widget 的 operator new 的实现非常简单:
void * Widget::operator new(std::size_t size) throw(std::bad_alloc) { NewHandlerHolder // install Widget's h(std::set_new_handler(currentHandler)); // new-handler
return ::operator new(size); // allocate memory // or throw
} // restore global // new-handler |
|
阅读(234) | 评论(0) | 转发(0) |