C++ Migration Guide

Exception Specifications

Under the old rules, all forms of operator new returned a null pointer if the allocation failed. Under the new rules, the ordinary forms of operator new throw an exception if allocation fails, and do not return any value. Special forms of operator new that return zero instead of throwing an exception are available. All versions of operator new and operator delete have an exception-specification. The declarations found in standard header <new> are:


namespace std {
      class bad_alloc;
      struct nothrow_t {};
      extern const nothrow_t nothrow;
}
// single-object forms
void* operator new(size_t size) throw(std::bad_alloc);
void* operator new(size_t size, const std::nothrow_t&) throw();
void operator delete(void* ptr) throw();
void operator delete(void* ptr, const std::nothrow_t&) throw();
// array forms
void* operator new[](size_t size) throw(std::bad_alloc);
void* operator new[](size_t size, const std::nothrow_t&) throw();
void operator delete[](void* ptr) throw();
void operator delete[](void* ptr, const std::nothrow_t&) throw();

Defensive code such as the following example no longer works as previously intended. If the allocation fails, the operator new that is called automatically from the new-expression throws an exception, and the test for zero never occurs.


T* p = new T;
if( p == 0 ) {           // No longer OK
    ...                  // Handle allocation failure
}
...                      // Use p

There are two solutions:

If you prefer not to use any exceptions in your code, you can use the second form. If you are using exceptions in your code, consider using the first form.

If you did not previously verify whether operator new succeeded, you can leave your existing code unchanged. It then aborts immediately on allocation failure instead of progressing to some point where an invalid memory reference occurs.