Reputation: 2698
Not to use in any implementation but just for the sake of understanding I am trying to explicitly call a destructor using an object and another *
to object.
CODE
#include<iostream>
using namespace std;
class A{
public :
A(){
cout<<"\nConstructor called ";
}
~A()
{
cout<<"\nDestructor called ";
}
};
int main()
{
A obj,*obj1;
obj1->~A();
obj.~A();
return 0;
}
OUTPUT
Now the problem is that I can't understand why destructor is called three times.
Even if the obj1
is not yet pointing to any object.
Note that I understand that the last two destructor calls are:
obj.~A()
;obj
.I am using DevC++ 5.5.1
Upvotes: 4
Views: 8438
Reputation: 626
the problem with destructor being invoked 3 times is actually quite simple.
In C++ objects constructed on the stack are destroyed automatically when they go out of scope. Whereas objects allocated with new must be explicitly deleted.
class MyClass
{
public:
int Value;
MyClass(int n) : Value(n) // initialize Value with n
{
cout << "MyClass::ctor(" << Value << ")" << endl;
}
~MyClass()
{
cout << "MyClass::dtor(" << Value << ")" << endl;
}
};
int main()
{
{
MyClass a(10); // create a local object
MyClass* b = new MyClass(20); // create a dynamically allocated object
delete b; // free dynamic memory and call destructor
} // a goes out of scope and destructor is automatically invoked
return 0;
}
So this doesn't really answer your question yet. Simply put, there is no way to avoid automatic destruction of local objects. The workaround is Cameron's example of using a local buffer and placement new:
MyClass* a = new (buffer) MyClass(10); // use placement new on a sufficient buffer
a->~MyClass(); // explicitly call destructor
If you must have local explicit objects, then you can always keep track whether your object actually has anything to destroy or not:
class MyClass2
{
public:
MyClass* Resource; // some resource we are managing
MyClass2() : Resource(nullptr) {}
MyClass2(int n) : Resource(new MyClass(n)) {}
~MyClass2()
{
if (Resource) // do we have anything to "destroy"?
{
delete Resource; // call destructor, free memory
Resource = nullptr; // ensure the resource is "destroyed" only once
}
}
};
So in effect, this only calls the "useful" part of the destructor if there really is something to "destroy".
Upvotes: -1
Reputation: 21647
Your code only works by a fluke.
int main()
{
A obj,*obj1;
obj1->~A(); // (1) Bad reference that works
obj.~A(); // (2) Explicit call to destructor
return 0;
} // (3) obj's destructor is called when obj goes out of scope
Upvotes: 9
Reputation: 98846
It's called three times, twice explicitly, and once when it goes out of scope.
The first explicit call is invalid, because the pointer is not initialized (this is undefined behaviour). In your case, it seems to have called the destructor function anyway, and since that doesn't use this
, nothing bad appeared to happen. There's nothing in the C++ standard that says method calls on uninitialized pointers are elided!
In general, you shouldn't call the destructor of an object more than one (explicitly or otherwise); however, there are valid cases for doing so explicitly. Consider:
{
alignas(alignof(A)) char data[sizeof(A)]; // Not an A object, so no
// call to dtor at scope end
A* ptr = new (data) A();
ptr->~A(); // object is now destructed but memory in `data` can be reused
}
Upvotes: 1
Reputation: 22644
obj1->~A();
You dereference the pointer obj1
which has not been initialized. That is undefined behaviour.
In this situation, anything can happen and nothing is guaranteed.
Upvotes: 3