new
ExpressionsAlthough the operator new
and operator delete
functions are intended to be used by new
expressions, they are ordinary functions in the library. As a result, ordinary code can call these functions directly.
In earlier versions of the language—before the allocator
(§ 12.2.2, p. 481) class was part of the library—applications that wanted to separate allocation from initialization did so by calling operator new
and operator delete
. These functions behave analogously to the allocate
and deallocate
members of allocator
. Like those members, operator new
and operator delete
functions allocate and deallocate memory but do not construct or destroy objects.
Differently from an allocator
, there is no construct
function we can call to construct objects in memory allocated by operator new
. Instead, we use the placement new
form of new
(§ 12.1.2, p. 460) to construct an object. As we’ve seen, this form of new
provides extra information to the allocation function. We can use placement new
to pass an address, in which case the placement new
expression has the form
new (place_address) type
new (place_address) type (initializers)
new (place_address) type [size]
new (place_address) type [size] { braced initializer list }
where place_address must be a pointer and the initializers provide (a possibly empty) comma-separated list of initializers to use to construct the newly allocated object.
When called with an address and no other arguments, placement new
uses operator new(size_t, void*)
to “allocate” its memory. This is the version of operator new
that we are not allowed to redefine (§ 19.1.1, p. 822). This function does not allocate any memory; it simply returns its pointer argument. The overall new
expression then finishes its work by initializing an object at the given address. In effect, placement new
allows us to construct an object at a specific, preallocated memory address.
When passed a single argument that is a pointer, a placement new
expression constructs an object but does not allocate memory.
Although in many ways using placement new
is analogous to the construct
member of an allocator
, there is one important difference. The pointer that we pass to construct
must point to space allocated by the same allocator
object. The pointer that we pass to placement new
need not point to memory allocated by operator new
. Indeed, as we’ll see in § 19.6 (p. 851), the pointer passed to a placement new
expression need not even refer to dynamic memory.
Just as placement new
is analogous to using allocate
, an explicit call to a destructor is analogous to calling destroy
. We call a destructor the same way we call any other member function on an object or through a pointer or reference to an object:
string *sp = new string("a value"); // allocate and initialize a string
sp->~string();
Here we invoke a destructor directly. The arrow operator dereferences the pointer sp
to obtain the object to which sp
points. We then call the destructor, which is the name of the type preceded by a tilde (~
).
Like calling destroy
, calling a destructor cleans up the given object but does not free the space in which that object resides. We can reuse the space if desired.