6

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.

user1873947
  • 1,781
  • 3
  • 27
  • 47
  • 2
    The issue is with `object.~a();` do not manually call the destructor. – andre Feb 06 '13 at 19:26
  • 4
    I don't want to do it, I just want to know what does destructor actually do. – user1873947 Feb 06 '13 at 19:27
  • Basicly it free the memory of the object back to to the system. All member variable destructor are also called by this code behind the sense. – andre Feb 06 '13 at 19:30
  • 2
    @user1873947: the destructor destroys all member variables. The main time you'd invoke a dtor directly is in conjunction with using placement new. – Jerry Coffin Feb 06 '13 at 19:30
  • 2
    Add a class B as your member variable, instead of set. Use cout in constructor/destructor of B and A to see what exactly happens. – joy Feb 06 '13 at 19:34
  • A *trivial* destructor does nothing, any other destructor does something even if the code looks like it does nothing – David Rodríguez - dribeas Feb 06 '13 at 20:06
  • @andre is member variable like `int` , `char`, ... have destructors also ? I think destructors are present only for object and class not for primitive data types. – Abhishek Mane May 16 '21 at 11:29

3 Answers3

11

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.

Lily Ballard
  • 182,031
  • 33
  • 381
  • 347
  • 2
    Maybe. If your class had a base class, or virtual functions, the destructor might do something as well. – James Kanze Feb 06 '13 at 19:29
  • That's what I wanted to know, it deletes member variables. Thanks, I will accept it. – user1873947 Feb 06 '13 at 19:29
  • @JamesKanze: True, but I'm assuming OP already knows that part. His example here has no inheritance. – Lily Ballard Feb 06 '13 at 19:30
  • 3
    @user1873947 It doesn't delete them (and that's not what Kevin wrote); it destructs them. – James Kanze Feb 06 '13 at 19:30
  • 2
    @user1873947: What James said. "delete" refers to the `delete` operator, which destructs the object and then deallocates the memory the object was in. In this case, you're only destructing, and a good thing too because your object is on the stack rather than allocated on the heap. – Lily Ballard Feb 06 '13 at 19:31
  • [link](https://stackoverflow.com/users/582/lily-ballard) what is non-POD , i did not get that, please elabborate. – GeekyCoder Dec 25 '19 at 10:34
  • @GeekyCoder POD is Plain Old Data, which are types that have no constructor, destructor, or virtual member functions. Also see https://stackoverflow.com/questions/146452/what-are-pod-types-in-c – Lily Ballard Dec 26 '19 at 23:44
6

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.

csd
  • 1,724
  • 10
  • 18
1

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.

Tyler Jandreau
  • 4,245
  • 1
  • 22
  • 47
  • Yeah that's what I said, guy. "Since your class has member variables myset, it's deallocating those when being manually called" – Tyler Jandreau Feb 06 '13 at 19:32