I'm calling the destructor to deallocate memory but it is not deleting my object. What is the reason behind it?
my code is like this:
class A
{
public:
int a;
A()
{
cout << "a" << endl;
}
};
class B :public A
{
public:
int b;
B()
{
cout << "b" << endl; a = 10; b = 20;
}
~B()
{
cout << a << b << endl;
}
};
and I am using it like:
int main()
{
{
B b;
b.~B();
b.b=100; // why this step is executed?
}
int x;
cin>>x;
return 0;
}
Why? Destructor does not deallocate memory occupied by the object. Never did.
A non-trivial destructor ends object's lifetime, but it doesn't end the object's storage duration. This means that memory remains allocated, it just becomes "raw" (uninitialized). So, in that sense it is destroying your object.
Meanwhile, a trivial destructor has no effect at all. Even if you call it explicitly, the object's lifetime does not end.
In your case the destructor
B::~B
is non-trivial though, which formally means that by calling it you ended your object's lifetime. You destroyed it as much a local object can be destroyed. But the memory remains. Attempting to access that memory as aB
object simply leads to undefined behavior.In fact, there's no way to manually deallocate memory occupied by a local object. Local memory is always deallocated automatically.
What you're doing is actually invoking undefined behavior ... just because you've called the destructor, does not mean that the memory is zeroed out or necessarily "reclaimed" and inaccessable (especially in the case of an automatic variable that was allocated on the stack and not the heap). It could be, but that is left up to the implementation, and typically that is not done due to performance reasons, which is typically the reason for using C++ in the first place. Therefore you can theoretically access the values at the memory address that the object was occupying after calling the destructor ... but again, it's undefined behavior, and you can run into pretty much anything from a segmentation fault, to a silent error that corrupts memory somewhere else, etc.
You do not call a destructor like that (well, you can but it's generally not done).
For automatic variables like your
b
, the destructor will be called at some point when the variable goes out of scope. You don't ever need to call the destructor explicitly.For objects allocated on the heap with
new
, the destructor will be called after youdelete
them. In this case, you also don't call the destructor explicitly.C++03 states in
12.4 Destructors
:You especially don't do what you're trying to do since the destructor will be called twice, once explicitly by you and once implicitly when
b
goes out of scope. From that same section of the standard:This text remains unchanged in the latest draft of C++11 that I have (n3225, November 2010) and it's unlikely it would have changed in essence between that and approval in August 2011.
Why wouldn't? Your object has been destroyed but its memory space is still around until it goes out of scope, where it will be destroyed again by the way. It's undefined behavior to do what you do.
Destructors were not designed to call them explicitly. Basically it is just another (special) method of class. If you want to Uninitialize your object and then still be able to use it you could make our own method:
Otherwise B will be deleted when out of scope:
It's executed because you wrote the code that said you wanted it to happen. The compiler is simply doing what you told it to do.
What you're doing probably doesn't "deallocate memory," as you suggested it would. Instead, it just calls the destructor. Destructors don't deallocate the memory occupied by the objects they're called on. They deallocate memory allocated by the object (such as by calling destructors of member variables, or calling
free
ordelete
on other things), but the memory of the object itself is deallocated elsewhere, either by the internal workings of thedelete
statement, or by the compiler when cleaning up automatic variables (which is what yourB b
declaration represents). Even the closing of the scope block probably doesn't deallocate any memory forb
; compilers usually figure out how much stack space they'll need for an entire subroutine and allocate it all upon entry. The memory occupied by thatB
object is reserved forb
upon entry to the inner scope, and upon exit, the destructor is called automatically.