1

I want to explicitly call the destructor of an object in C++ to destroy that object.

This is just a simple program to experiment with the features of the programming languages. I have a default constructor which sets the internal data member to 1, and overloaded constructor which sets the internal data member to the parameter, and a destructor which displays the internal data member of the just destroyed object. There is also a function which prints the internal data member.

#include <iostream>
using std::cout;
using std::endl;

class myClass {
  public:
   myClass()
   {
     i = 1;
     cout << "default ";
     cout << "constructor called with " << this->i << endl;
   }

   myClass(int i)
   {
     this->i = i;
     cout << "constructor called with " << this->i << endl;
   }

   ~myClass()
   {
     cout << "object " << i << " destroyed!" << endl;
   }

   void printData()
   {
     cout << "object's data is " << i << endl;
   }
  private:
   int i;  // private data member
};

int main() {
  myClass a;
  myClass b;
  myClass c(8);

  a.printData();
  b.printData();
  c.printData();

  /* I want to explicitly destroy object b. */
  b.~myClass();
  b.printData();

  /* all the destructors get called when the objects go out of scope */

  return 0;
}

My reasoning is this: I think that the destructor causes the object to be destroyed, so it no longer exists in the memory. After I explicitly call the destructor, I should be no longer able to use that object again, since it is destroyed. However, I am able to call a function of the object and print the value of the internal data member. Did manually calling the destructor fail to destroy the object? What's going on here? Output:

default constructor called with 1
default constructor called with 1
constructor called with 8
object's data is 1
object's data is 1
object's data is 8
object 1 destroyed!
object's data is 1
object 8 destroyed!
object 1 destroyed!
object 1 destroyed!

Does calling the destructor destroy the object, or is calling the destructor a RESULT OF destroying the object?

Galaxy
  • 2,363
  • 2
  • 25
  • 59
  • 4
    _"Note that calling a destructor directly for an ordinary object, such as a local variable, invokes undefined behavior when the destructor is called again, at the end of scope."_ from: http://en.cppreference.com/w/cpp/language/destructor So basically don't do this. – Richard Critten Jun 14 '18 at 20:14
  • 1
    The ONLY time you can safely call a destructor MANUALLY is when the object is constructed using [placement-new](https://en.cppreference.com/w/cpp/language/new#Placement_new), which is not the case in any of your examples. If you want deterministic control over when an object is destroyed, put it in a scope that you control, or use `new`/`delete` (or smart wrappers). But either way, once an object has been destructed, it is not safe to access its members anymore. So calling `printData()` after calling `~myClass()` is **undefined behavior**. – Remy Lebeau Jun 14 '18 at 20:15
  • 1
    Calling the destructor does not free the memory. Also, even if it did, just because you free memory it doesn't necessarily just go away. It may linger. – Galik Jun 14 '18 at 20:15
  • Does calling the destructor destroy the object, or is calling the destructor a RESULT OF destroying the object? – Galaxy Jun 14 '18 at 20:18
  • Manually calling destructor won't destroy/free the object. You should use delete. `delete b;` in your case. You might not want to call d'tor manually, consider re-architecting your object structure to avoid such a scenario. – Sunil Jun 14 '18 at 20:18
  • @Sunil `delete b;` will not work in the OP's example since `b` is not being allocated with `new`, eg: `myClass *b = new myClass;`. – Remy Lebeau Jun 14 '18 at 20:19
  • @RemyLebeau "The ONLY time you can safely call a destructor MANUALLY is when the object is constructed using placement-new" - what about construct a local object, explicitly call the destructor, and then use placement new to construct a new object in the same memory. I *think* that is legal and safe (bicbw). – Martin Bonner supports Monica Jun 14 '18 at 20:20
  • @MartinBonner you are right, there is one case for that: [Is calling destructor manually always a sign of bad design?](https://stackoverflow.com/questions/14187006/): "*With C++ 2011 there is another reason to use explicit destructor calls: When using generalized unions, it is necessary to explicitly destroy the current object and create a new object using placement new when changing the type of the represented object. Also, when the union is destroyed, it is necessary to explicitly call the destructor of the current object if it requires destruction.*" – Remy Lebeau Jun 14 '18 at 20:22
  • Re: "I want to explicitly call the destructor of an object in C++ to destroy that object." -- Why? Needing to do that is **extremely** rare; it's expert use only. Don't do it. The destructor will run when the object goes out of scope. – Pete Becker Jun 14 '18 at 20:58
  • Why? Because I want to know "what if". Knowing the flaws and pitfalls of C++ and their (mis)use cases can be useful for avoiding them. I gain knowledge about how the programming language itself works, by examining the edge cases. – Galaxy Jun 14 '18 at 21:14

1 Answers1

1

After I explicitly call the destructor, I should be no longer able to use that object again, since it is destroyed

That's right. Only that it's C++ and instead of "you are no longer able" as in "you'll be warned when you do bad things", it's more like "you may be shot in the foot at any random point in the future without warning if you do bad things" (aka "undefined behavior").

In your particular example, you destroy the object, and it ceases to logically exist. The memory may still be allocated or even contain some old data. However, trying to access it is undefined behavior. It may "kind of work" on your specific combination of compiler, compiler flags, source code, OS and moon phase, it may work differently later, it technically may even wipe your hard drive.

Also, as you've declared the object in a local variable, it gets automatically destroyed second time when it goes out of the scope. That's also undefined behavior, but it does not really matter is your program's behavior is already completely undefined.

You may try catching such things with dynamical analysis like Valgrind, AddressSanitizer or UndefinedBehaviorSanitizer, but they provide no guarantees.

yeputons
  • 8,478
  • 34
  • 67