Home > Articles > Programming > C/C++

C++ Reference Guide

Hosted by

Toggle Open Guide Table of ContentsGuide Contents

Close Table of ContentsGuide Contents

Close Table of Contents

nothrow new

Last updated Jan 1, 2003.

I've already discussed several flavors of operator new, including the ordinary versions of new and placement new. Standard C++ has another version of this operator, called nothrow new. In the following sections I will describe its raison d'être and usage.

A Bit of History

Until the early 1990s, operator new behaved very much like standard C's malloc(), as far as allocation failures were concerned. When it failed to allocated a memory block of the requested size, it would return a NULL pointer. In those days, a typical new expression would look like this:

//pre-standard C++
CWindow * p;
p = new DerivedWind;
if (!p) //NULL indicates a failure
{
 cout<<"allocation failure!"
 exit(1);
}
//...continue normally

Programs had to check the pointer returned from new to verify that the allocation was successful; a pointer with a non-zero value indicated success.

This behavior was changed in the early 1990s. Instead of returning a NULL pointer, new throws an exception to indicate a failure. Because exceptions were rather new at that time, and because legacy code that relied on the original new behavior was still widely used, vendors were rather slow in adopting this change. Today, however, most existing compilers implement new in a standard-compliant manner.

Standard Compliant new

Let's examine the behavior of standard-compliant new more carefully. As previously said, operator new throws an exception of type std::bad_alloc in case of failure. This means that testing the return value like this is utterly wrong:

p = new DerivedWind;
if (!p) //not to be used under ISO compliant compilers
{
 cout<<"allocation failure!"
 exit(1);
}

There are several problems with this code. The if condition is never evaluated in the event of an allocation failure, because the exception thrown by new has already transferred control to a matching catch() clause, if one exists. If no matching handler is found, C++ automatically calls function terminate() that terminates the program unconditionally.

Unfortunately, quite a few programmers still use this coding practice even today, not knowing how dangerous and erroneous it is. A standard compliant version of this code should look like this:

try
{
 p = new DerivedWind;
}
catch (std::bad_alloc &ba) 
{
 cout<<"allocation failure!"
 //...additional cleanup
}

There are, however, certain cases in which the pre-standard behavior of new is needed. For example, embedded systems don't always support exceptions. In such environments, nothrow new can be rather useful.

nothrow new's Interface

The standard header file <new> defines a struct called std::nothrow_t like this:

struct nothrow_t {}; //defined in namespace std

This empty struct merely serves as a policy enforcing parameter in the following overloaded versions of new:

//declarations appear in <new>
void* operator new (size_t size, const std::nothrow_t &);
void* operator new[] (void *v, const std::nothrow_t &nt);

<new> also defines a global object of type std::notrow_t:

extern const nothrow_t nothrow;

The definition of a global object enables all C++ programs to use nothrow new uniformly, by using the same argument name.

Putting nothrow new to Work

By using nothrow new one can easily make the previous code listing standard compliant, while retaining its original structure and semantics:

//standard C++ code
#include <new> //required for nothrow new

CWindow p;
p = new(std::nothrow) DerivedWind;
if (!p) //fine now
{
 cout<<"allocation failure!"
 exit(1);
}
//...continue normally

Notice that no changes were made to the original code, save the new(nothrow) expression. If you want to test the behavior of this code fragment in case of an allocation failure, try to allocate a huge amount of memory:

//force an allocation failure to test 
//the behavior of nothrow new
p = new(std:::nothrow) DerivedWind[1000000000];
if (!p)
{
 cout<<"allocation failure!"
 exit(1);
}

Summary

The existence of nothrow new exemplifies the constant conflicts that C++ creators have faced during its 20 years of existence. On the one hand, they've attempted to ensure that existing code wouldn't break due to changes in the core language. On the other hand, they haven't avoided necessary extensions and modifications.

That said, nothrow new isn't necessarily a transitory feature. As stated previously, C++ is used in resource constrained environments in which exceptions aren't supported. Such environments necessitate the use nothrow new in new code as well.