What does empty destructor do?

2019-05-06 22:07发布

问题:

I heard that empty destructor doesn't do anything and calling it doesn't remove the object. But in the code:

#include <iostream>
#include <set>


class a
{
public:
    ~a() 
    {}
std::set <int> myset;
};

int main()
{
a object;
object.myset.insert(55);
object.~a();
object.myset.insert(20);
std::cout << object.myset.size();
}

I get: "* glibc detected * /.app: double free or corruption (fasttop):" and then "ABORT".

If it matters I have c++11 flag enabled. So what does empty constructor actually do? It does something and I read it doesn't.

回答1:

Your destructor may look empty, but it's actually destructing the member variables. In this case, it's destructing myset, so the subsequent insert(20) is crashing.

If your class had no non-POD member variables then the empty destructor would truly do nothing.



回答2:

Your question mentions a couple different issues.

First, there's the error message. The "Double free" is probably because the destructor is getting called twice: once by you, and once by the C++ runtime when the variable is no longer in scope (at the closing brace of your main function).

Second, there's your question about the empty destructor not removing the object. Indeed it does not remove the object from memory, but it DOES destroy its member variables. So after your manual call to the destructor, the memory for object is still allocated, but myset is no longer valid.



回答3:

Destructor is called when going out of scope. I would highly recommend not calling the destructor, and then attempting to access members or member functions of the parent class. Since your class has member variables myset, it's deallocating those when being manually called, hence the segmentation error.

Think of the destructor as the "clean up" when you're absolutely done with your object. Under no circumstances should you call it manually.

Pseudocode:

class MyClass {
public:
  MyClass() {
    std::cout << "Constructor" << std::endl;
  }

  ~MyClass() {
     std::cout << "~Destructor" << std::endl;
   }
}

int main(int argc, char** argv) {
   MyClass myClass;
   return 0;
}

You should see this output:

Constructor

~Destructor

As you can see, no manual call is needed.