13.37 <new>

The <new> header declares types and functions related to dynamic memory management. (See Chapter 3 for more information about the new and delete expressions, including placement new and delete, and the operator new and operator delete functions.) Most programs do not need to use <new>. The header is typically used by libraries and programs that implement their own operator new and operator delete functions or otherwise provide custom management of dynamic memory.

If a source file uses the standard new and delete expressions, it does not need to #include <new>. You can also use the pointer placement new without including this header. In order to use the nothrow placement new, or catch bad_alloc, you must include this header.

Most programs do not call the operators directly, but instead use new and delete expressions, and the compiler generates calls using the appropriate operators. Library implementors sometimes make direct calls to the operators, especially to allocate uninitialized memory. See <memory> earlier in this chapter for examples.

Some specialized applications might implement the global operator new and operator delete functions or provide additional overloaded operators for specialized circumstances, such as allocating memory that is shared across process boundaries. If you write your own operator new, you should obey the following guidelines:

  • Implement operator new and operator new[].

  • Implement operator delete and operator delete[]. Even if your operator new is a placement new function, you should have a corresponding placement delete function (which is called if a new expression throws an exception).

  • Return a pointer that meets the strictest alignment requirements of any type. (Note that malloc in <cstdlib> and the standard operator new function return aligned pointers.)

  • Handle out-of-memory situations by throwing bad_alloc (or a class that derives from bad_alloc) or returning a null pointer. If you return a null pointer, your operator new function must have an empty exception specification.

  • If operator new and operator delete are member functions, include the static keyword as a reminder to the human reader. The compiler always treats these functions as static, even if you omit the keyword.

Example 13-32 shows a trivial implementation of the global operator new and operator delete functions.

Example 13-32. Implementing operator new and operator delete with malloc and free
#include <cstdlib>

#include <new>

   

void* operator new(std::size_t size) throw(std::bad_alloc)

{

  void* ptr = std::malloc(size);

  if (ptr == 0)

    throw std::bad_alloc(  );

  return ptr;

}

   

void* operator new(std::size_t size, const std::nothrow_t&)

throw(  )

{

  return std::malloc(size);

}

   

void* operator new[](std::size_t size) throw(std::bad_alloc)

{

  return operator new(size);

}

   

void* operator new[](std::size_t size, const std::nothrow_t&)

throw(  )

{

  return operator new(size, std::nothrow);

}

   

void operator delete(void* ptr) throw(  )

{

  std::free(ptr);

}

   

void operator delete(void* ptr, const std::nothrow_t&)

throw(  )

{

  std::free(ptr);

}

   

void operator delete[](void* ptr) throw(  )

{

  operator delete(ptr);

}

   

void operator delete[](void* ptr, const std::nothrow_t&)

throw(  )

{

  operator delete(ptr);

}
bad_alloc class Exception class for failed memory allocation

class bad_alloc : public exception {

public:

  bad_alloc(  ) throw(  );

  bad_alloc(const bad_alloc&) throw(  );

  bad_alloc& operator=(const bad_alloc&) throw(  );

  virtual ~bad_alloc(  ) throw(  );

  virtual const char* what(  ) const throw(  );

};

figs/acorn.gif

The bad_alloc class is an exception class that is thrown when operator new is unable to fulfill a request to allocate memory. As with any of the standard exception classes, what( ) returns an implementation-defined character string.

See Also

operator new, set_new_handler, exception in <exception>

nothrow object Requests null pointer return when out of memory

struct nothrow_t {};

extern const nothrow_t nothrow;

The nothrow object is used in placement new expressions to request that the new operator return a null pointer instead of throwing bad_alloc if the memory allocation request cannot be fulfilled.

The nothrow_t type does not do anything; it is used only in overloaded placement new and delete operators.

Note that nothrow is also accepted by overloaded operator delete for symmetry with new. The nothrow version of operator delete behaves just like the ordinary operator delete. Like any placement delete function, it is called only if the placement new expression throws an exception.

See Also

operator delete, operator new

operator delete Global operator delete

void operator delete(void* ptr) throw(  );

void operator delete[](void* ptr) throw(  );

void operator delete(void* ptr, const std::nothrow_t&) throw(  );

void operator delete[](void* ptr, const std::nothrow_t&) throw(  );

void operator delete(void* ptr, void*) throw(  );

void operator delete[](void* ptr, void*) throw(  );

The global operator delete function is called from a delete expression to free memory. The memory, which ptr points to, must have been returned by a corresponding call to operator new or be a null pointer. You must not call operator delete more than once for the same pointer. If ptr is null, operator delete returns without doing anything.

The first two versions of operator delete free the memory that ptr points to, which must have been allocated by calling the plain form of operator new. These forms of operator delete are called from a delete expression. The first is called for a scalar delete, and the second is called for an array delete[].

The remaining forms are called only when the corresponding placement new expression throws an exception during construction. The nothrow functions free the memory that ptr points to. The last two forms do nothing. See the new expression in Chapter 3 to learn how and when placement operator delete is called.

Unlike other identifiers in the standard library, operator delete is global and is not in the std namespace. Also, unlike with other functions in the standard library, you can provide your own implementation of operator delete, which replaces the standard implementation. You cannot, however, replace the last two versions of delete with your own implementation.

See Also

operator new

operator new Global operator new

void* operator new(std::size_t size) throw(std::bad_alloc);

void* operator new(std::size_t size, const std::nothrow_t&) throw(  );

void* operator new[](std::size_t size) throw(std::bad_alloc);

void* operator new[](std::size_t size, const std::nothrow_t&) throw(  );

void* operator new(std::size_t size, void* ptr) throw(  );

void* operator new[](std::size_t size, void* ptr) throw(  );

The global operator new function allocates memory and returns a pointer to the newly allocated memory. The memory must later be released by a corresponding delete expression or an explicit call to operator delete.

The first version of new allocates at least size bytes of memory, suitably aligned to store any type, and returns a pointer to the memory. If the request cannot be fulfilled, it throws bad_alloc.

The second version is like the first, but it returns a null pointer instead of throwing bad_alloc if sufficient memory cannot be allocated.

The third version is like the first, but it allocates memory for storing an array of objects. It might allocate more than size bytes to permit the library to store additional bookkeeping information. You must use the array form of delete[] to free this memory.

The fourth version is like the third, but it returns a null pointer instead of throwing bad_alloc if sufficient memory cannot be allocated.

To allocate memory, the operator new functions first try to allocate size bytes. If they cannot, they call the handler function set by the most recent call to set_new_handler. Then they try again to allocate size bytes. This loop repeats until the request is fulfilled or the handler function fails to return. The nothrow versions of the function return 0 if the most recent call to set_new_handler was a null pointer or if the new handler function throws bad_alloc.

The final two versions do nothing except return ptr. These forms permit placement new expressions to specify a memory location where an object will be constructed.

Unlike other identifiers in the standard library, operator new is global and is not in the std namespace. Also, unlike with other functions in the standard library, you can provide your own implementation of operator new, which replaces the standard implementation. You cannot, however, replace the last two versions of new with your own implementation.

See Also

nothrow object, operator delete, set_new_handler function

set_new_handler function Sets handler for obtaining memory

typedef void (*new_handler)(  );

new_handler set_new_handler(new_handler new_p) throw(  );

The set_new_handler function stores a function pointer for a function that obtains additional memory from the operating system for use by the new operator. When the default operator new is unable to fulfill a request to allocate memory, it calls the handler that was set by the most recent call to set_new_handler. This handler must do one of the following:

  • Obtain more memory from the host environment

  • Throw bad_alloc (or a type that derives from bad_alloc)

  • Call abort( ) or exit( ) to halt the program

The return value is the pointer to the previous handler, or 0 for the first call to set_new_handler.