Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is memory released when a destructor is called or when `delete` is called?

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?

like image 769
bobobobo Avatar asked Aug 23 '11 01:08

bobobobo


People also ask

Does destructor release memory?

You should not explicitly call the destructor, since doing so won't release the memory that was allocated for the Fred object itself.

Do destructors deallocate memory?

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.

What happens when the destructor is called?

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 ( ~ ).

Is destructor called on delete?

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.


2 Answers

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!

like image 83
templatetypedef Avatar answered Oct 21 '22 08:10

templatetypedef


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.

like image 37
Kerrek SB Avatar answered Oct 21 '22 09:10

Kerrek SB