The new operator (C++ only)

The new operator provides dynamic storage allocation.

Read syntax diagramSkip visual syntax diagramnew operator syntax
 
>>-+----+--new--+---------------------+--+-(--type--)-+--------->
   '-::-'       '-(--argument_list--)-'  '-new_type---'
 
>--+-------------------------+---------------------------------><
   '-(--+---------------+--)-'
        '-initial_value-'
 

If you prefix new with the scope resolution operator (::), the global operator new() is used. If you specify an argument_list, the overloaded new operator that corresponds to that argument_list is used. The type is an existing built-in or user-defined type. A new_type is a type that has not already been defined and can include type specifiers and declarators.

An allocation expression containing the new operator is used to find storage in free store for the object being created. The new expression returns a pointer to the object created and can be used to initialize the object. If the object is an array, a pointer to the initial element is returned.

You cannot use the new operator to allocate function types, void, or incomplete class types because these are not object types. However, you can allocate pointers to functions with the new operator. You cannot create a reference with the new operator.

When the object being created is an array, only the first dimension can be a general expression. All subsequent dimensions must be constant integral expressions. The first dimension can be a general expression even when an existing type is used. You can create an array with zero bounds with the new operator. For example:

char * c = new char[0];

In this case, a pointer to a unique object is returned.

An object created with operator new() or operator new[]() exists until the operator delete() or operator delete[]() is called to deallocate the object's memory. A delete operator or a destructor will not be implicitly called for an object created with a new that has not been explicitly deallocated before the end of the program.

If parentheses are used within a new type, parentheses should also surround the new type to prevent syntax errors.

In the following example, storage is allocated for an array of pointers to functions:

void f();
void g();

int main(void)
{
      void (**p)(), (**q)();
      // declare p and q as pointers to pointers to void functions
      p = new (void (*[3])());
      // p now points to an array of pointers to functions
      q = new void(*[3])(); // error
      // error - bound as 'q = (new void) (*[3])();'
      p[0] = f;  // p[0] to point to function f
      q[2] = g;  // q[2] to point to function g
      p[0]();    // call f()
      q[2]();    // call g()
      return (0);
}

However, the second use of new causes an erroneous binding of q = (new void) (*[3])().

The type of the object being created cannot contain class declarations, enumeration declarations, or const or volatile types. It can contain pointers to const or volatile objects.

For example, const char* is allowed, but char* const is not.

Placement syntax

Arguments specifying an allocated storage location can be supplied to new by using the argument_list, also called the placement syntax. If placement arguments are used, a declaration of operator new() or operator new[]() with these arguments must exist. For example:

#include <new>
using namespace std;

class X
{
public:
      void* operator new(size_t,int, int){ /* ... */ }
};

// ...

int main ()
{
      X* ptr = new(1,2) X;
}

The placement syntax is commonly used to invoke the global placement new function. The global placement new function initializes an object or objects at the location specified by the placement argument in the placement new expression. This location must address storage that has previously been allocated by some other means, because the global placement new function does not itself allocate memory. In the following example, no new memory is allocated by the calls new(whole) X(8);, new(seg2) X(9);, or new(seg3) X(10); Instead, the constructors X(8), X(9), and X(10) are called to reinitialize the memory allocated to the buffer whole.

Because placement new does not allocate memory, you should not use delete to deallocate objects created with the placement syntax. You can only delete the entire memory pool (delete whole). In the example, you can keep the memory buffer but destroy the object stored in it by explicitly calling a destructor.

#include <new>
class X
{
   public:
      X(int n): id(n){ }
      ~X(){ }
   private:
      int id;
      //	...
};

int main()
{
   char* whole = new char[ 3 * sizeof(X) ];  // a 3-part buffer
   X * p1 = new(whole) X(8);                 // fill the front
   char* seg2 = &whole[ sizeof(X) ];         // mark second segment
   X * p2 = new(seg2) X(9);                  // fill second segment
   char* seg3 = &whole[ 2 * sizeof(X) ];     // mark third segment
   X * p3 = new(seg3) X(10);                 // fill third segment

   p2->~X();   // clear only middle segment, but keep the buffer
   // ...
   return 0;
}

The placement new syntax can also be used for passing parameters to an allocation routine rather than to a constructor.

Related information