The operator new
allocates memory for objects, and the operator delete
frees the memory allocated by the matching
operator new
. It is possible to customize these operations, either for a specific class (by overloading these operators in the class) or
globally (by defining them in the global namespace, they will replace the default version).
If the operator delete
is not overloaded alongside the operator new
, the program will call its default implementation,
which may not be suitable for the custom memory allocation strategy used by the overloaded operator new
.
For instance, if the operator new
draws memory from a preallocated buffer instead of allocating memory, the operator
delete
should not call the free
function to release the memory. Reciprocally, if the operator new
allocate memory
with malloc
, the operator delete
must call free
.
On the other hand, if the operator delete
is overloaded without overloading the operator new
, it is suspicious because it
may not correctly release the memory allocated by the default operator new
.
By defining the operator delete
along with the operator new
, the memory is deallocated in a way consistent with the
custom allocation strategy used by the operator new
.
Up to this point, we mentioned operator new
and operator delete
, but it is a simplification. There are many different
forms of operator new
and operator delete
(for a single object or an array, with an extra
alignment parameter… see the links for a full list), and the consistency between new and delete should be enforced for each form.
For instance, if void * operator new[]( std::size_t count, std::align_val_t al );
is defined (for arrays, with extra alignment), then
void operator delete[]( void* ptr, std::align_val_t al ) noexcept;
should be defined too.
Additionally, since C++17, it is possible to define a version of the delete operator with an additional size argument, alongside the unsized
version of operator delete
. When overloading these operators in a class, defining both a sized and an unsized version of operator delete
is useless, since the unsized version will always be preferred. However, for free replacement, it is necessary to specify both versions since the
language does not specify which version will be called.
What is the potential impact?
Overloading only one of the two operators may result in your program consuming more and more memory over time, eventually leading to a crash.
Deallocating memory that was not allocated with the corresponding strategy results in undefined behavior.