new expression

From cppreference.com
 
 
C++ language
General topics
Flow control
Conditional execution statements
Iteration statements
Jump statements
Functions
function declaration
lambda function declaration
function template
inline specifier
exception specifications (deprecated)
noexcept specifier (C++11)
Exceptions
Namespaces
Types
decltype specifier (C++11)
Specifiers
cv specifiers
storage duration specifiers
constexpr specifier (C++11)
auto specifier (C++11)
alignas specifier (C++11)
Initialization
Literals
Expressions
alternative representations
Utilities
Types
typedef declaration
type alias declaration (C++11)
attributes (C++11)
Casts
implicit conversions
const_cast conversion
static_cast conversion
dynamic_cast conversion
reinterpret_cast conversion
C-style and functional cast
Memory allocation
new expression
Classes
Class-specific function properties
Special member functions
Templates
class template
function template
template specialization
parameter packs (C++11)
Miscellaneous
Inline assembly
 

Creates and initializes objects with dynamic storage duration, that is, objects whose lifetime is not limited by the scope in which they were created.

Contents

[edit] Syntax

::(optional) new (placement_params)(optional) ( type ) initializer(optional) (1)
::(optional) new (placement_params)(optional) type initializer(optional) (2)
1) Attempts to create an object of type type, which may be array type, and may include the type specifier auto(since C++11).
2) Same, but type cannot include parentheses:
new int(*[10])(); // parser error: parsed as (new int) (*[10]) ()
new (int (*[10])()); // OK: allocates an array of 10 pointers to functions

Note: If auto is used in type, then initializer is not optional: it is required to deduce the type to use in place of auto: auto p = new auto('c'); // creates a single object of type char. p is a char*

[edit] Explanation

The new expression attempts to allocate storage and then attempts to construct and initialize either a single unnamed object, or an unnamed array of objects in the allocated storage. The new-expression returns a prvalue pointer to the constructed object or, if an array of objects was constructed, a pointer to the initial element of the array.

If type is an array type, all dimensions other than the first must be specified as constant positive integral expressions, but the first dimension may be any expression that is implicitly convertible to int. This is the only way to directly create an array with size defined at runtime, such arrays are often referred to as dynamic arrays:

int n = 42;
double a[n][5]; // Error
auto p1 = new double[n][5]; // OK
auto p2 = new double[5][n]; // Error

If the first dimension is negative or too large, std::bad_array_new_length may be thrown (since C++11). The first dimension of zero is acceptable.

Note: std::vector offers similar functionality for one-dimensional dynamic arrays.

[edit] Allocation

The new-expression allocates storage by calling the appropriate allocation function. If type is a non-array type, the name of the function is operator new(). If type is an array type, the name of the function is operator new[]().

As described in allocation function, the C++ program may provide global and class-specific replacements for these functions. If the new-expression begins with the optional :: operator, as in ::new T or ::new T[n], class-specific replacements will be ignored (the function is looked up in global scope). Otherwise, if T is a class type, it is looked up in the scope of T first.

When calling the allocation function, the new-expression passes the number of bytes requested as the first argument, of type size_t, which is exactly sizeof(T) for non-array T.

Array allocation may supply unspecified overhead, which may vary from one call to new to the next. The pointer returned by the new-expression will be offset by that value from the pointer returned by the allocation function. Many implementations use the array overhead to store the number of objects in the array which is used by operator delete[] to call the correct number of destructors. In addition, if the new-expression is used to allocate an array of char or an array unsigned char, it may request additional memory from the allocation function if necessary to guarantee correct alignment of objects of all types no larger than the requested array size, if one is later placed into the allocated array.

If placement_params are provided, they are passed to the allocation function as additional arguments:

new T;      //  calls operator new( sizeof(T) )
new T[5];   //  calls operator new[]( sizeof(T)*5 + overhead)
new(2,f) T; //  calls operator new( sizeof(T), 2, f)

Such allocation functions are known as "placement new", after the standard allocation function void* operator new(std::size_t, void*), which simply returns its second argument unchanged. This is used to construct objects in allocated storage:

char* ptr = new char[sizeof(T)]; // allocate memory
T* tptr = new(ptr) T; // construct in allocated storage ("place")
tptr->~T();   // destruct
delete[] ptr; // deallocate

Note: this functionality is encapsulated by the member functions of the Allocator classes.

If the allocation function return a null pointer, which is possible if the non-throwing overload was selected, e.g. with new(std::nothrow) T;, then the new-expression returns immediately, it does not attempt to initialize an object or to call a deallocation function.

[edit] Construction

The object created by a new expression is initialized according to the following rules:

  • For non-array type, the single object is constructed in the acquired memory area.
  • If type is an array type, an array of objects is initialized.

If initialization terminates by throwing an exception (e.g. from the constructor), the new-expression calls the appropriate deallocation function: operator delete() for non-array type, operator delete[]() for array type. The deallocation function is looked up in global scope if the new expression used the ::new syntax, otherwise it is looked up in the scope of T first, if T is a class type. If no deallocation function is found, memory is not deallocated. The value obtained earlier from the allocation function is passed as the first argument to the deallocation function.

[edit] Memory leaks

The objects created by new expressions (objects with dynamic storage duration) persist until the pointer returned by the new expression is used in a matching delete-expression. If the original value of pointer is lost, the object becomes unreachable and cannot be deallocated: a memory leak occurs.

This may happen if the pointer is assigned to:

int* p = new int(7); // dynamically allocated int with value 7
p = NULL; // memory leak

or if the pointer goes out of scope:

void f()
{
    int* p = new int(7);
} // memory leak

or due to exception

void f()
{
   int* p = new int(7);
   g();      // may throw
   delete p; // OK if no exception
} // memory leak if g() throws

To simplify management of dynamically-allocated objects, the result of a new-expression is often stored in a smart pointer: std::unique_ptr, std::shared_ptr, or std::auto_ptr(deprecated). These pointers guarantee that the delete expression is executed in the situations shown above.

[edit] Keywords

new