The behaviors of new
operator and operator new
is different.
Relationship between ‘new
operator’ and ‘operator new
’
Consider the following code:
|
|
The new
operator here is built into the language and always does the same two things:
- first, it calls
operator new
to allocate enough memory to hold an object of the type requested. - second, it calls a constructor to initialize an object in the memory that was allocated.
Thus, when compiler sees the code above, they must generate code equivalent to this:
|
|
So if we want to create an object on the heap, use the new
operator and it both allocates memory and calls a constructor for the object.
However, if we want to do some customized behaviors, we may consider following options:
-
if we only want to allocate memory, just call
operator new
directly:1
void *rawMemory = operator new(sizeof(string));
-
if we want to customize the memory allocation that takes place when heap objects are created, write our own version of
operator new
and use thenew
operator, which will automatically invoke the custom version ofoperator new
-
if we want to construct an object in memory we’ve already got a pointer to, use placement
new
.A special version of
oeprator new
called placementnew
allows us to construct an object in the memory that’s already been allocated, which is helpful for applications using shared memory or memory-mapped I/O, where objects must be placed at specific addresses or in memory allocated by special routines:1 2 3 4 5 6 7 8 9 10
class Widget { public: Widget(int widgetSize); ... }; Widget * constructWidgetInBuffer(void *buffer, int widgetSize) { return new (buffer) Widget(widgetSize); }
Here, an additional argument (
buffer
) is being specified for the implicit call that thenew
operator makes to a special version ofoperator new
known as placementnew
in standard C++ library1:1 2 3 4
void * operator new(size_t, void *location) { return location; }
All placement
new
has to do is return the pointer that’s passed into it, because the memory for the object is already known. The unused (but mandatory)size_t
parameter has no name to keep compilers from complaining about its not being used (MECpp item 6).
Deletion and memory deallocation
The delete
operator also includes two steps: destructing the object and deallocating the memory occupied by that object. The second part of memory deallocation is performed by the operator delete
function:
|
|
Hence, for a pointer to string ps
, delete ps;
causes compilers to generate code that approximately corresponds to this:
|
|
Some implications:
- If we want to deal with raw, uninitialized memory, we should call
operator new
to get memory andoperator delete
to return it to the system (the C++ equivalent of callingmalloc
andfree
):
|
|
- If we use placement
new
to create an object in some memory, we should avoid using thedelete
operator on that memory:
|
|
Arrays
For array allocation:
|
|
The new
being used is still the new
operator, but the behavior here is slightly different from the case for single-object creation:
- in the first step, memory is allocated by
operator new[]
instead ofoperator new
- in the second step, the constructor is called for each object in the array, so here the default constructor for
string
is called 10 times.
Similarly, when the delete
operator is used on an array, it calls a destructor for each array element and then calls operator delete[]
to deallocate the memory.
Just as we can replace or overload operator new
and operator delete
, we can do the same trick to operator new []
and operator delete []
to seize the control of memrory allocation and deallocation for arrays.
-
To use placement
new
, all we have to do is is#include <new>
. ↩︎