Reputation: 175
I'm quite confused about destructors in C++. For example, when we call delete in the code below, it calls first the destructor of Derived1 and then the destructor of Base, then what happens? What about the pointer dynamically allocated? Also, what happens if I call directly the destructor of Derived1 without delete or when I call them both?
#include <iostream>
using namespace std;
class Base
{
public:
Base(){
cout << "Base Constructor Called\n";
}
~Base(){
cout << "Base Destructor called\n";
}
};
class Derived1: public Base
{
public:
Derived1(){
cout << "Derived constructor called\n";
}
~Derived1(){
cout << "Derived destructor called\n";
}
};
int main()
{
Derived1 *b = new Derived1();
delete b;
}
Upvotes: 1
Views: 885
Reputation:
Lifetime, or the availability/existence span of time:
Object
beginning from it's being declared and defined with/without
object initialization in a scope, up to the running point (current
IP as on low level) is exiting out of that scope, at which the
destructors of the object is executed to restore back all of memory
claimed and do other necessary things to maintaining
Allocation memory request (asked to OS by new, malloc etc instruction)
beginning from being requested by such instruction with the pointer
created internally and returned as the only base reference, up to
that pointer is referred again to restore the claimed memory portion
by delete instruction
but for object memory allocation it will automatically call its destructor
a_class *p = new a_class(1,2,3);
(1,2,3) is initialization of the object being referenced by p pointer
So of course, as the pointer lifetime is the same as explained, if it's finished by exiting out of its scope before deleting is executed then the memory keeps reserved, spared and immutably living, made alive by OS will stuff up the memory resource and hence the understanding of memory leak famous meaning/term
Upvotes: 0
Reputation: 238281
when we call delete in the code below, it calls first the destructor of Derived1 and then the destructor of Base
Strictly speaking, delete
destroys only the most derived object which is Derived1
in this case. It is the destructor of Derived1
that calls the destructors of its own subobjects such as Base
.
then what happens?
A deallocation function will be called with the pointer value as an operand. The function will release the previously allocated memory, which ends the duration of the region of storage. That region may then be re-used for storing other dynamic objects created with a new
expression.
what happens if I call directly the destructor of Derived1
Then the object will be destroyed. The destruction ends the lifetime of the object, and (because the class is not trivially destructible) invokes the destructor.
without delete
Then the memory allocation will not be released and cannot be used for further allocations. This is often considered to be a "memory leak".
what happens ... when I call them both?
Then the behaviour of the program will be undefined.
Upvotes: 4
Reputation: 22152
After calling the destructors of the object, as you noted in your question, the delete
expression calls operator delete
, a special function which deallocates memory, and operator delete
frees the memory allocation that b
points to and that was previously allocated by a call to operator new
(which the new
expression in your code called).
After deallocation happened (i.e. after operator delete
returned), the pointer b
becomes invalid and cannot be used anymore.
Calling the destructor directly ends the lifetime of the pointed-to object (and will also call the base and member destructors), but does not deallocate memory by a call to operator delete
. You could reuse the memory that the object occupied and the pointer points to, to place a new object into it (with a so-called placement-new expression), but the object that you called the destructor on will not be usable anymore. Trying to use it will cause undefined behavior. (There are exceptions to this for class types with trivial destructor pre-C++20.)
Using the delete
expression on the pointer after having called the (non-trivial) destructor causes undefined behavior, because delete
calls the destructor again, but outside the object's lifetime, which was ended by the previous destructor call.
Calling the destructor after having called delete
causes undefined behavior as well, because it would use an invalid pointer.
Upvotes: 4