shining cento in book reading: handle out of memory problem for new operator -by register a global SetNewHandler
Template/inheritance based NewHandler support, a good solution to add memory allocation failure support at class level
the template is used to provide unique currentHandler pointer for each class, the inheritance is to provide newhandler support for the class
So, if you want to have your own class support new handler, do it like the code below:
template<class T> // "mixin-style" base class class NewHandlerSupport { // for class-specific public: // set_new_handler support
static new_handler set_new_handler(new_handler p);
static void * operator new(size_t size);
private:
static new_handler currentHandler;
};
template<class T>
new_handler NewHandlerSupport<T>::set_new_handler(new_handler p)
{
new_handler oldHandler = currentHandler;
currentHandler = p;
return oldHandler;
}
template<class T>
void * NewHandlerSupport<T>::operator new(size_t size)
{
new_handler globalHandler =
std::set_new_handler(currentHandler);
void *memory;
try {
memory = ::operator new(size);
}
catch (std::bad_alloc&) {
std::set_new_handler(globalHandler);
throw;
}
std::set_new_handler(globalHandler);
return memory;
}
client code without template:
void noMoreMemory(); // decl. of function to
// call if memory allocation
// for X objects fails
X::set_new_handler(noMoreMemory);
// set noMoreMemory as X's
// new-handling function
X *px1 = new X; // if memory allocation
// fails, call noMoreMemory
string *ps = new string; // if memory allocation
// fails, call the global
// new-handling function
// (if there is one)
X::set_new_handler(0); // set the X-specific
// new-handling function
// to nothing (i.e., null)
X *px2 = new X; // if memory allocation
// fails, throw an exception
// immediately. (There is
// no new-handling function
// for class X.)
Client code for the template version:
template<class T>
new_handler NewHandlerSupport<T>::currentHandler
"no throw" support for old compiler based code, return 0 instead of exception under insufficient memory situation
Until 1993, C++ required thatoperatornewreturn 0 when it was unable to satisfy a memory request. The current behavior is foroperatornewto throw astd::bad_allocexception, but a lot of C++ was written before compilers began supporting the revised specification. The°C++ standardization committee didn't want to abandon the established test-for-0 code base, so they provided alternative forms ofoperatornew(andoperator— see Item 8 that continue to offer the traditional failure-yields-0 behavior. These forms are called "nothrow" forms because, well, they never do anew[] throw, and they employnothrowobjects (defined in the standard header<new>) at the point wherenewisused:
class Widget { ... };
Widget *pw1 = new Widget; // throws std::bad_alloc if
// allocation fails
if (pw1 == 0) ... // this test must fail
Widget *pw2 =
new (nothrow) Widget; // returns 0 if allocation
// fails
if (pw2 == 0) ... // this test may succeed
浙公网安备 33010602011771号