Assume you have an object of class Fool
.
class Fool
{
int a,b,c;
double* array ;
//...
~Fool()
{
// destroys the array..
delete[] array ;
}
};
Fool *fool = new Fool() ;
Now, I know you shouldn't, but some fool calls the destructor on fool
anyway. fool->~Fool();
.
Does that mean fool
's memory is freed, (ie a,b,c are invalid) or does that mean only whatever deallocations in ~Fool()
function occur (ie the array is deleted only?)
So I guess my question is, is a destructor just another function that gets called when delete
is called on an object, or does it do more?
You should not explicitly call the destructor, since doing so won't release the memory that was allocated for the Fred object itself.
Destructors are usually used to deallocate memory and do other cleanup for a class object and its class members when the object is destroyed. A destructor is called for a class object when that object passes out of scope or is explicitly deleted.
A destructor is a member function that is invoked automatically when the object goes out of scope or is explicitly destroyed by a call to delete . A destructor has the same name as the class, preceded by a tilde ( ~ ).
When delete is used to deallocate memory for a C++ class object, the object's destructor is called before the object's memory is deallocated (if the object has a destructor). If the operand to the delete operator is a modifiable l-value, its value is undefined after the object is deleted.
If you write
fool->~Fool();
You end the object's lifetime, which invokes the destructor and reclaims the inner array
array. The memory holding the object is not freed, however, which means that if you want to bring the object back to life using placement new:
new (fool) Fool;
you can do so.
According to the spec, reading or writing the values of the fields of fool
after you explicitly invoke the destructor results in undefined behavior because the object's lifetime has ended, but the memory holding the object should still be allocated and you will need to free it by invoking operator delete
:
fool->~Fool();
operator delete(fool);
The reason to use operator delete
instead of just writing
delete fool;
is that the latter has undefined behavior, because fool
's lifetime has already ended. Using the raw deallocation routine operator delete
ensures that the memory is reclaimed without trying to do anything to end the object's lifetime.
Of course, if the memory for the object didn't come from new
(perhaps it's stack-allocated, or perhaps you're using a custom allocator), then you shouldn't use operator delete
to free it. If you did, you'd end up with undefined behavior (again!). This seems to be a recurring theme in this question. :-)
Hope this helps!
The destructor call does just that, it calls the destructor. Nothing more and nothing less. Allocation is separate from construction, and deallocation from destruction.
The typical sequence is this:
1. Allocate memory
2. Construct object
3. Destroy object (assuming no exception during construction)
4. Deallocate memory
In fact, if you run this manually, you will have to call the destructor yourself:
void * addr = ::operator new(sizeof(Fool));
Fool * fp = new (addr) Fool;
fp->~Fool();
::operator delete(addr);
The automatic way of writing this is of course Fool * fp = new Fool; delete fp;
. The new
expression invokes allocation and construction for you, and the delete
expression calls the destructor and deallocates the memory.
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