0

I learned that the destructor is called when an object goes out of scope and also the destructor deletes the objects. Ok fine, but what's happening here?

I'm calling the destructor explicitly, if it deletes the object then why is the destructor implicitly called? Even though there no object now because it's already deleted with the explicitly destructor calling. Sorry may be I'm wrong about explicitly and implicitly But try to understand my problem.

#include <iostream>
using namespace std;
class A{
    public:
        A(){
            cout << "Constructor" << endl;
        }
        ~A(){
            cout << "Destructor" << endl;
        }

};
int main(){
    A obj;
    obj.~A();
    cout << "End" << endl;
}

Now

obj.~A();

The above line deletes the object. Then why again is the destructor called? Even though no object is there.

Output:

Constructor
Destructor
End
Destructor
tux3
  • 7,171
  • 6
  • 39
  • 51
Asif Mushtaq
  • 3,658
  • 4
  • 44
  • 80
  • 3
    `obj.~A();` You don't ever call the destructor function manually, that leads to trouble. – πάντα ῥεῖ Jun 07 '15 at 16:05
  • 1
    @πάνταῥεῖ But can you explain what's happening in my code? and why should not call destructor manually? – Asif Mushtaq Jun 07 '15 at 16:06
  • 2
    @Asif, you seem to be confused about what a destructor does. Specifically, it does *not* free the storage associated with the object. So it's wrong to write that `obj.~A()` *deletes* the object. – Frédéric Hamidi Jun 07 '15 at 16:13
  • @FrédéricHamidi this point that I was trying to clear. `Destructor not deletes the object when called.` Thanks – Asif Mushtaq Jun 07 '15 at 16:21
  • 1
    It isn't "do not ever call the destructor manually". It is "only call the destructor manually if you are doing placement new on properly aligned storage prior to calling it, because you are writing a union-like or container type and manually managing object lifetime at a low level". Admittedly that is really close to "never". – Yakk - Adam Nevraumont Jun 07 '15 at 16:32
  • @Yakk thanks to participate I understood I should never call it manually when I write `delete[] ptr` etc in destructor. But can you also clear my confusion? `Destructor not deletes the object when it's called.` this line is fine? – Asif Mushtaq Jun 07 '15 at 16:34

4 Answers4

5

An object which goes out of scope has its destructor called. That is an unchangeable guarantee which is mandated by the C++ language standard. It doesn't matter if you've manually called the destructor beforehand; when it goes out of scope, the destructor will be called. If you've written your destructor such that bad things happen if it's called twice, or if the extra behavior which the compiler inserts into the destructor code doesn't want to be called twice, bad things will happen.

This is one of many reasons why you should never manually call a destructor.

Sneftel
  • 40,271
  • 12
  • 71
  • 104
  • I understood I should never call it manually when I write `delete[] ptr` etc in destructor. But can you also clear my confusion? `Destructor not deletes the object when it's called with empty body`. this line is fine? – Asif Mushtaq Jun 07 '15 at 16:41
  • 4
    @AsifMushtaq No. A destructor does _not_ delete the object, ever. Deleting an object does call the destructor, but you should only delete an object that was allocated by `new`. Explicitly calling the destructor is only used when the object has been constructed using placement new. – James Kanze Jun 07 '15 at 16:55
1

Your object does not contain any pointers. It does not free any objects in the destructor when called so no harm is done when it is called multiple times. If the destructor deletes pointers and those pointers are not set to 0, which is often the case in destructors, then the second call of the destructor would be harmful because it would cause a memory error.

QuentinUK
  • 2,997
  • 21
  • 20
1

The destructor does not delete the object, it destructs it. And unless the object is a POD type (basically, something you could define in C), destructing an already destructed object is undefined behavior. Since all variables will automatically have their destructor called when their lifetime ends, you should never explicitly call the destructor on them. Similarly, if you have created the object with a non-placement form of new: explicitly calling the destructor will not free the memory; you should use delete, which calls the destructor and then frees the memory.

The only time you should explicitly call the destructor is when you have used placement new to construct the object, in order to separate allocation and initialization. Today, such techniques should really be considered advanced, and it is rare for a programmer to need them.

James Kanze
  • 150,581
  • 18
  • 184
  • 329
1

Your provided class doesn't manage any data, so its destructor doesn't have any objects to free. That's why you're able to call the destructor twice with no consequences. Here's an example class that would fail the same test:

#include <iostream>


class A {
 public:
  A() {
    std::cout << "constructing..." << '\n';
    val = new int;
  }

  ~A() {
    std::cout << "destructing..." << '\n';
    delete val;
  }

 private:
  int* val;
};


int main() {
  A obj;
  obj.~A();
  std::cout << "End" << '\n';
  return 0;
}

The constructor allocates space on the heap for val, and the destructor runs delete to free up that space. ~A() is called twice in main() (first explicitly, then implicitly), which understandably causes a memory error.

Check out this link for more info on how destructors work: https://isocpp.org/wiki/faq/dtors

Patrick
  • 455
  • 4
  • 11
  • why you removed using namespace std; ? and used it separately ? any logic behind it? – Asif Mushtaq Jun 07 '15 at 17:11
  • It's just good practice. Here's the generally accepted answer: http://stackoverflow.com/questions/1452721/why-is-using-namespace-std-considered-bad-practice Although here it doesn't actually matter, since it's just an example program. – Patrick Jun 07 '15 at 18:34