tags:

views:

359

answers:

6
+10  Q: 

Destructors in C++

Does the destructor deallocate memory assigned to the object which it belongs to or is it just called so that it can perform some last minute housekeeping before the object is deallocated by the compiler?

+3  A: 

The destructor is called to allow the object to perform cleanup as well as to destroy any other objects the object itself has created.

The OS will deal with deallocating the object itself after finishing the destructor.

damirault
+28  A: 

The 'compiler' doesn't delete anything. It creates code that does things at runtime.

When you write delete somePointer; the compiler, in essence, writes:

  if ( has_virtual_destructor( * somePointer  ) ) {
       // virtual dispatch to a compiler-generated function
      dynamic_cast< true_dynamic_type * >(somePointer)->destroy_dynamic_type();
       /* contents of true_dynamic_type::destroy_dynamic_type() {
              this->~true_dynamic_type();
              operator delete( this); // executed within class context
       } */
  } else {
      somePointer->~ClassName();
      operator delete(somePointer);
  }

In other words, the destructor gets called, and then operator delete gets called to free the storage.

If the destructor is virtual, a virtual dispatch is used to perform the entire operation on the object in its most-derived form. A common way of implementing this is to add hidden arguments to every virtual destructor.

bmargulies
That's a lot of upvotes ;v) … maybe mention the cast to true dynamic type in the case of a virtual destructor. (And, the way `operator delete` lookup works, `delete` is in fact called from within an "in-charge" virtual destructor. Not mentioning this could be confusing cf a profile trace.)
Potatoswatter
@potatoswatter: feel feee to edit. I can't explain the landslide, I just typed up the obvious.
bmargulies
One minor nitpick: this `if (has_virtual_destructor…` is *not* executed at runtime. The *compiler* can decide for each type (thus depending only on the *static* type) whether it has a virtual or non-virtual destructor and emit appropriate code for both situations. Not sure what happens when you try to `delete` a `void*` but my guess is that this will be UB.
Konrad Rudolph
A: 

1) destructor doesn't belong to object, it belongs to class

2) It calls destructor for all the user defined types (class objects) within its class.

3) Cleanup is optional activity which is done only if it is really required

hype
A: 

The memory is deallocated right after the destructor function exits and before execution returns to the "delete" call or point where an object instance goes out of scope. In theory it is possible to set up a different memory manager to handle new and delete, but that would be an explicit change of the default behavior.

Erik Hermansen
A: 

More specifically, nobody but the programmer deallocates memory in C++. If the object is on the stack, it is resident in the memory space of the program, and takes space during the lifetime of the program. If it is on the heap, whoever created the object is responsible for deallocating it. Thats what delete does. This brings us to the destructor - if you create objects in your class, the destructor allows you to delete them as the class leaves scope. It lets you "turn out the lights as you leave".

Matt
There is no "the programmer." If I, a programmer, write a class with a member variable of type std::vector, I need not, and must not write code to delete it. The compiler will automatically generate code to call the std::vector destructor that some other programmer somewhere wrote at some time, and made available in the header file <vector>.
Jive Dadson
A: 

Destructors automatically call the destructors on member variables of the object being destroyed. Those destructors may or may not free up memory. However, a pointer has no destructor, or if you prefer, a pointer's destructor does nothing. It does not free the memory that it points to. If an object contains a pointer to an object obtained from "new" or "malloc," it is up to the programmer of that object to make the destructor do the right thing. You should program your destructor to "delete" or "free" the memory if it is conceptually part of the object being destructed. For example, a "vector" object typically obtains memory from the heap, because the amount of memory required is not generally known at compile time. That memory is conceptually part of the vector object, and thus the programmer of the vector class must call "delete" on it in the destructor. Standard Template Library classes like std::vector do it properly.

On the other hand, some objects contain references to other objects. A dictionary or index will contain references (pointers) to objects that are not conceptually part of them. That memory must not be freed by the destructor. (If you remove your phone number from the phone book, you do not want your phone to automatically disappear.)

There are exceptions that the novice need not be concerned with at first. One is when the object and its containers are programmed to use reference-counting, and the referenced object is not really freed until the last object referring to it lets it go. Another exception is in the case of "placement new."

Jive Dadson