7 Expressions [expr]

7.6 Compound expressions [expr.compound]

7.6.2 Unary expressions [expr.unary]

7.6.2.7 New [expr.new]

The new-expression attempts to create an object of the type-id or new-type-id to which it is applied.
The type of that object is the allocated type.
This type shall be a complete object type, but not an abstract class type or array thereof ([intro.object], [basic.types], [class.abstract]).
[Note
:
Because references are not objects, references cannot be created by new-expressions.
— end note
]
[Note
:
The type-id may be a cv-qualified type, in which case the object created by the new-expression has a cv-qualified type.
— end note
]
If a placeholder type appears in the type-specifier-seq of a new-type-id or type-id of a new-expression, the allocated type is deduced as follows: Let init be the new-initializer, if any, and T be the new-type-id or type-id of the new-expression, then the allocated type is the type deduced for the variable x in the invented declaration ([dcl.spec.auto]):
T x init ;
[Example
:
new auto(1);                    // allocated type is int
auto x = new auto('a');         // allocated type is char, x is of type char*

template<class T> struct A { A(T, T); };
auto y = new A{1, 2};           // allocated type is A<int>
— end example
]
The new-type-id in a new-expression is the longest possible sequence of new-declarators.
[Note
:
This prevents ambiguities between the declarator operators &, &&, *, and [] and their expression counterparts.
— end note
]
[Example
:
new int * i;                    // syntax error: parsed as (new int*) i, not as (new int)*i
The * is the pointer declarator and not the multiplication operator.
— end example
]
[Note
:
Parentheses in a new-type-id of a new-expression can have surprising effects.
[Example
:
new int(*[10])();               // error
is ill-formed because the binding is
(new int) (*[10])();            // error
Instead, the explicitly parenthesized version of the new operator can be used to create objects of compound types:
new (int (*[10])());
allocates an array of 10 pointers to functions (taking no argument and returning int).
— end example
]
— end note
]
Objects created by a new-expression have dynamic storage duration ([basic.stc.dynamic]).
[Note
:
The lifetime of such an object is not necessarily restricted to the scope in which it is created.
— end note
]
When the allocated object is not an array, the result of the new-expression is a pointer to the object created.
When the allocated object is an array (that is, the noptr-new-declarator syntax is used or the new-type-id or type-id denotes an array type), the new-expression yields a pointer to the initial element (if any) of the array.
[Note
:
Both new int and new int[10] have type int* and the type of new int[i][10] is int (*)[10]
— end note
]
The attribute-specifier-seq in a noptr-new-declarator appertains to the associated array type.
Every constant-expression in a noptr-new-declarator shall be a converted constant expression ([expr.const]) of type std​::​size_­t and its value shall be greater than zero.
[Example
:
Given the definition int n = 42, new float[n][5] is well-formed (because n is the expression of a noptr-new-declarator), but new float[5][n] is ill-formed (because n is not a constant expression).
— end example
]
If the type-id or new-type-id denotes an array type of unknown bound ([dcl.array]), the new-initializer shall not be omitted; the allocated object is an array with n elements, where n is determined from the number of initial elements supplied in the new-initializer ([dcl.init.aggr], [dcl.init.string]).
If the expression in a noptr-new-declarator is present, it is implicitly converted to std​::​size_­t.
The expression is erroneous if:
  • the expression is of non-class type and its value before converting to std​::​size_­t is less than zero;
  • the expression is of class type and its value before application of the second standard conversion ([over.ics.user])70 is less than zero;
  • its value is such that the size of the allocated object would exceed the implementation-defined limit; or
  • the new-initializer is a braced-init-list and the number of array elements for which initializers are provided (including the terminating '\0' in a string-literal) exceeds the number of elements to initialize.
If the expression is erroneous after converting to std​::​size_­t:
When the value of the expression is zero, the allocation function is called to allocate an array with no elements.
A new-expression may obtain storage for the object by calling an allocation function ([basic.stc.dynamic.allocation]).
If the new-expression terminates by throwing an exception, it may release storage by calling a deallocation function.
If the allocated type is a non-array type, the allocation function's name is operator new and the deallocation function's name is operator delete.
If the allocated type is an array type, the allocation function's name is operator new[] and the deallocation function's name is operator delete[].
[Note
:
An implementation is required to provide default definitions for the global allocation functions ([basic.stc.dynamic], [new.delete.single], [new.delete.array]).
A C++ program can provide alternative definitions of these functions ([replacement.functions]) and/or class-specific versions ([class.free]).
The set of allocation and deallocation functions that may be called by a new-expression may include functions that do not perform allocation or deallocation; for example, see [new.delete.placement].
— end note
]
If the new-expression begins with a unary ​::​ operator, the allocation function's name is looked up in the global scope.
Otherwise, if the allocated type is a class type T or array thereof, the allocation function's name is looked up in the scope of T.
If this lookup fails to find the name, or if the allocated type is not a class type, the allocation function's name is looked up in the global scope.
An implementation is allowed to omit a call to a replaceable global allocation function ([new.delete.single], [new.delete.array]).
When it does so, the storage is instead provided by the implementation or provided by extending the allocation of another new-expression.
During an evaluation of a constant expression, a call to an allocation function is always omitted.
[Note
:
Only new-expressions that would otherwise result in a call to a replaceable global allocation function can be evaluated in constant expressions ([expr.const]).
— end note
]
The implementation may extend the allocation of a new-expression e1 to provide storage for a new-expression e2 if the following would be true were the allocation not extended:
  • the evaluation of e1 is sequenced before the evaluation of e2, and
  • e2 is evaluated whenever e1 obtains storage, and
  • both e1 and e2 invoke the same replaceable global allocation function, and
  • if the allocation function invoked by e1 and e2 is throwing, any exceptions thrown in the evaluation of either e1 or e2 would be first caught in the same handler, and
  • the pointer values produced by e1 and e2 are operands to evaluated delete-expressions, and
  • the evaluation of e2 is sequenced before the evaluation of the delete-expression whose operand is the pointer value produced by e1.
[Example
:
void can_merge(int x) {
  // These allocations are safe for merging:
  std::unique_ptr<char[]> a{new (std::nothrow) char[8]};
  std::unique_ptr<char[]> b{new (std::nothrow) char[8]};
  std::unique_ptr<char[]> c{new (std::nothrow) char[x]};

  g(a.get(), b.get(), c.get());
}

void cannot_merge(int x) {
  std::unique_ptr<char[]> a{new char[8]};
  try {
    // Merging this allocation would change its catch handler.
    std::unique_ptr<char[]> b{new char[x]};
  } catch (const std::bad_alloc& e) {
    std::cerr << "Allocation failed: " << e.what() << std::endl;
    throw;
  }
}
— end example
]
When a new-expression calls an allocation function and that allocation has not been extended, the new-expression passes the amount of space requested to the allocation function as the first argument of type std​::​size_­t.
That argument shall be no less than the size of the object being created; it may be greater than the size of the object being created only if the object is an array and the allocation function is not a non-allocating form ([new.delete.placement]).
For arrays of char, unsigned char, and std​::​byte, the difference between the result of the new-expression and the address returned by the allocation function shall be an integral multiple of the strictest fundamental alignment requirement of any object type whose size is no greater than the size of the array being created.
[Note
:
Because allocation functions are assumed to return pointers to storage that is appropriately aligned for objects of any type with fundamental alignment, this constraint on array allocation overhead permits the common idiom of allocating character arrays into which objects of other types will later be placed.
— end note
]
When a new-expression calls an allocation function and that allocation has been extended, the size argument to the allocation call shall be no greater than the sum of the sizes for the omitted calls as specified above, plus the size for the extended call had it not been extended, plus any padding necessary to align the allocated objects within the allocated memory.
The new-placement syntax is used to supply additional arguments to an allocation function; such an expression is called a placement new-expression.
Overload resolution is performed on a function call created by assembling an argument list.
The first argument is the amount of space requested, and has type std​::​size_­t.
If the type of the allocated object has new-extended alignment, the next argument is the type's alignment, and has type std​::​align_­val_­t.
If the new-placement syntax is used, the initializer-clauses in its expression-list are the succeeding arguments.
If no matching function is found then
  • if the allocated object type has new-extended alignment, the alignment argument is removed from the argument list;
  • otherwise, an argument that is the type's alignment and has type std​::​align_­val_­t is added into the argument list immediately after the first argument;
and then overload resolution is performed again.
[Example
:
  • new T results in one of the following calls:
    operator new(sizeof(T))
    operator new(sizeof(T), std::align_val_t(alignof(T)))
    
  • new(2,f) T results in one of the following calls:
    operator new(sizeof(T), 2, f)
    operator new(sizeof(T), std::align_val_t(alignof(T)), 2, f)
    
  • new T[5] results in one of the following calls:
    operator new[](sizeof(T) * 5 + x)
    operator new[](sizeof(T) * 5 + x, std::align_val_t(alignof(T)))
    
  • new(2,f) T[5] results in one of the following calls:
    operator new[](sizeof(T) * 5 + x, 2, f)
    operator new[](sizeof(T) * 5 + x, std::align_val_t(alignof(T)), 2, f)
    
Here, each instance of x is a non-negative unspecified value representing array allocation overhead; the result of the new-expression will be offset by this amount from the value returned by operator new[].
This overhead may be applied in all array new-expressions, including those referencing a placement allocation function, except when referencing the library function operator new[](std​::​size_­t, void*).
The amount of overhead may vary from one invocation of new to another.
— end example
]
[Note
:
Unless an allocation function has a non-throwing exception specification, it indicates failure to allocate storage by throwing a std​::​bad_­alloc exception ([basic.stc.dynamic.allocation], [except], [bad.alloc]); it returns a non-null pointer otherwise.
If the allocation function has a non-throwing exception specification, it returns null to indicate failure to allocate storage and a non-null pointer otherwise.
— end note
]
If the allocation function is a non-allocating form ([new.delete.placement]) that returns null, the behavior is undefined.
Otherwise, if the allocation function returns null, initialization shall not be done, the deallocation function shall not be called, and the value of the new-expression shall be null.
[Note
:
When the allocation function returns a value other than null, it must be a pointer to a block of storage in which space for the object has been reserved.
The block of storage is assumed to be appropriately aligned and of the requested size.
The address of the created object will not necessarily be the same as that of the block if the object is an array.
— end note
]
A new-expression that creates an object of type T initializes that object as follows:
The invocation of the allocation function is sequenced before the evaluations of expressions in the new-initializer.
Initialization of the allocated object is sequenced before the value computation of the new-expression.
If the new-expression creates an object or an array of objects of class type, access and ambiguity control are done for the allocation function, the deallocation function ([class.free]), and the constructor ([class.ctor]) selected for the initialization (if any).
If the new-expression creates an array of objects of class type, the destructor is potentially invoked ([class.dtor]).
If any part of the object initialization described above71 terminates by throwing an exception and a suitable deallocation function can be found, the deallocation function is called to free the memory in which the object was being constructed, after which the exception continues to propagate in the context of the new-expression.
If no unambiguous matching deallocation function can be found, propagating the exception does not cause the object's memory to be freed.
[Note
:
This is appropriate when the called allocation function does not allocate memory; otherwise, it is likely to result in a memory leak.
— end note
]
If the new-expression begins with a unary ​::​ operator, the deallocation function's name is looked up in the global scope.
Otherwise, if the allocated type is a class type T or an array thereof, the deallocation function's name is looked up in the scope of T.
If this lookup fails to find the name, or if the allocated type is not a class type or array thereof, the deallocation function's name is looked up in the global scope.
A declaration of a placement deallocation function matches the declaration of a placement allocation function if it has the same number of parameters and, after parameter transformations ([dcl.fct]), all parameter types except the first are identical.
If the lookup finds a single matching deallocation function, that function will be called; otherwise, no deallocation function will be called.
If the lookup finds a usual deallocation function and that function, considered as a placement deallocation function, would have been selected as a match for the allocation function, the program is ill-formed.
For a non-placement allocation function, the normal deallocation function lookup is used to find the matching deallocation function ([expr.delete]).
[Example
:
struct S {
  // Placement allocation function:
  static void* operator new(std::size_t, std::size_t);

  // Usual (non-placement) deallocation function:
  static void operator delete(void*, std::size_t);
};

S* p = new (0) S;   // error: non-placement deallocation function matches
                    // placement allocation function
— end example
]
If a new-expression calls a deallocation function, it passes the value returned from the allocation function call as the first argument of type void*.
If a placement deallocation function is called, it is passed the same additional arguments as were passed to the placement allocation function, that is, the same arguments as those specified with the new-placement syntax.
If the implementation is allowed to introduce a temporary object or make a copy of any argument as part of the call to the allocation function, it is unspecified whether the same object is used in the call to both the allocation and deallocation functions.
If the conversion function returns a signed integer type, the second standard conversion converts to the unsigned type std​::​size_­t and thus thwarts any attempt to detect a negative value afterwards.
This may include evaluating a new-initializer and/or calling a constructor.