What exactly is the purpose of having both a destructor and Overloading delete
for a class?
In what types of scenarios should one use both?
When you allocate an object with a new
expression like:
X *x = new X();
It basically does two separate things: it allocates some memory, then creates an object in that memory, roughly equivalent to:
void *temp = operator new(sizeof(X));
X *x = new(temp) X;
The first just allocates a block of raw memory. The second just takes that block of raw memory, and creates an object in it.
Roughly the reverse happens when you delete an object:
delete x;
...is roughly equivalent to something like:
x->~X();
operator delete(static_cast<void *>(x));
So, operator new and operator delete just deal with allocating and freeing raw memory. The constructor and destructor just deal with creating and destroying objects in memory that's already been allocated. After the destructor runs to destroy the object in some memory, then operator delete
is used to free the memory itself.
By default, there's one global pair of operator new
and operator delete
that are used to allocate objects of all types. You can replace those if you want. You can also provide an operator new
and operator delete
for a specific class (as static member functions1). In this case, those functions will be used only for managing memory for objects of that class. This tends to be particularly useful for things like classes that are extremely small, and you expect to allocate a large number of objects of this class. Many memory managers aren't particularly efficient when dealing with an extremely large number of extremely small items, so overloading in this case can improve (reduce) memory usage quite a bit.
There are also operator new[]
and operator delete[]
, which are used when/if you allocate/free arrays of objects. operator new[]
is just passed a number of bytes to allocate, and operator delete
is just passed a block of raw memory to free. If you decided to overload these, you might presume that they'd be used primarily for larger blocks of memory and optimize appropriately, but that's about the only difference from the non-array versions.
As a rule, I'd avoid using new
to allocate arrays (ever) rendering these entirely irrelevant. And no, they can't be/aren't used by an allocator if you create something like an std::vector<T>
either. Well, I suppose if you didn't mind abusing the system quite thoroughly, you could create an allocator for use with std::vector
that used new char[size]
to manage the allocation, in which case it would use one of these, but I find it hard to imagine that anybody would really do that. Maybe at one time when C++ wasn't well understood, but nowadays it would stick out like a sore thumb in any decent code base.
1. One minor oddity: the compiler "knows" these must always be static, so even if you don't use the static
key-word when you declare/define them, they'll be static anyway.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With