new and delete (C++)

In the C++ programming language,

new anddelete are a pair of language constructs that perform dynamic memory allocation, object construction and object destruction.

Overview

Except for a form called the "placement new", thenew operator denotes a request for memory allocation on a process's heap. If sufficient memory is available,new initialises the memory, calling object constructors if necessary, and returns the address to the newly allocated and initialised memory. Anew request, in its simplest form, looks as follows:

p = new T;

wherep is a previously declared pointer of typeT (or some other type to which aT pointer can be assigned, such as a superclass ofT). The default constructor forT, if any, is called to construct aT instance in the allocated memory buffer.

If not enough memory is available in the free store for an object of typeT, thenew request indicates failure by throwing an exception of typestd::bad_alloc. This removes the need to explicitly check the result of an allocation.

The deallocation counterpart ofnew isdelete, which first calls the destructor (if any) on its argument and then returns the memory allocated bynew back to the free store. Every call tonew must be matched by a call todelete; failure to do so causes a memory leak.

new syntax has several variants that allow finer control over memory allocation and object construction. A function call-like syntax is used to call a different constructor than the default one and pass it arguments, e.g.,

p = new T(argument);

calls a single-argumentT constructor instead of the default constructor when initializing the newly allocated buffer.

A different variant allocates and initialises arrays of objects rather than single objects:

p = new T [N];

This requests a memory buffer from the free store that is large enough to hold a contiguous array ofN objects of typeT, and calls the default constructor on each element of the array.

Memory allocated with thenew[] must be deallocated with thedelete[] operator, rather thandelete. Using the inappropriate form results in undefined behavior. C++ compilers are not required to generate a diagnostic message for using the wrong form.

The C++11 standard specifies an additional syntax,

p = new T[N] {initializer1, ..., initializerN};

that initializes eachp[i] toinitializeri+1.

Error handling

Ifnew cannot find sufficient memory to service an allocation request, it can report its error in three distinct ways. Firstly, the ISO C++ standard allows programs to register a custom function called anew_handler with the C++ runtime; if it does, then this function is called whenevernew encounters an error. Thenew_handler may attempt to make more memory available, or terminate the program if it can't.

If nonew_handler is installed,new instead throws an exception of typestd::bad_alloc. Thus, the program does not need to check the value of the returned pointer, as is the habit in C; if no exception was thrown, the allocation succeeded.

The third method of error handling is provided by the variant formnew(std::nothrow), which specifies that no exception should be thrown; instead, a null pointer is returned to signal an allocation error.

Overloading

Thenew operator can be overloaded so that specific types (classes) use custom memory allocation algorithms for their instances. For example, the following is a variant of the singleton pattern where the firstnew Singleton call allocates an instance and all subsequent calls return this same instance:

#include <cstdlib>
#include <cstddef>

class Singleton {
public:
  static void* operator new(std::size_t size) {
    if (!instance) {
      instance = std::malloc(size);
    }
    refcount++;
    return instance;
  }

  static void operator delete(void*) noexcept {
    if (--refcount == 0) {
      std::free(instance);
      instance = nullptr;
    }
  }

private:
  static void* instance = nullptr;
  static std::size_t refcount = 0;
};

This feature was available from early on in C++'s history, although the specific overloading mechanism changed. It was added to the language because object-oriented C++ programs tended to allocate many small objects withnew, which internally used the C allocator (see § Relation to malloc and free); that, however, was optimized for the fewer and larger allocations performed by typical C programs. Stroustrup reported that in early applications, the C functionmalloc was "the most common performance bottleneck in real systems", with programs spending up to 50% of their time in this function.

Relation to malloc and free

Since standard C++ subsumes the C standard library, the C dynamic memory allocation routinesmalloc,calloc,realloc andfree are also available to C++ programmers. The use of these routines is discouraged for most uses, since they do not perform object initialization and destruction.new anddelete were, in fact, introduced in the first version of C++ (then called "C with Classes") to avoid the necessity of manual object initialization.

In contrast to the C routines, which allow growing or shrinking an allocated array withrealloc, it is not possible to change the size of a memory buffer allocated bynew[]. The C++ standard library instead provides a dynamic array (collection) that can be extended or reduced in itsstd::vector template class.

The C++ standard does not specify any relation betweennew/delete and the C memory allocation routines, butnew anddelete are typically implemented as wrappers aroundmalloc andfree. Mixing the two families of operations, e.g.,free'ingnew'ly allocated memory ordelete'ingmalloc'd memory, causes undefined behavior and in practice can lead to various catastrophic results such as failure to release locks and thus deadlock.

See also

References

Uses material from the Wikipedia article new and delete (C++), released under the CC BY-SA 4.0 license.