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 newto 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 newdirectly:1void *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 newand use thenewoperator, 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 newcalled placementnewallows 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 10class 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 thenewoperator makes to a special version ofoperator newknown as placementnewin standard C++ library1:1 2 3 4void * operator new(size_t, void *location) { return location; }All placement
newhas 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_tparameter 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 newto get memory andoperator deleteto return it to the system (the C++ equivalent of callingmallocandfree):
|
|
- If we use placement
newto create an object in some memory, we should avoid using thedeleteoperator 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
stringis 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>. ↩︎