The Art of Destruction
Of all the features of C++, I think that one that programmers seem to overlook is the class destructor.
To most, the destructor is simply a way to free allocated memory. And if you are using a language with garbage collection, this narrow use is obviated. In fact, this is one of the memes I have heard the most from Java developers.
However, the destructor may clean up more than memory. For example, a file object may use its destructor to make sure a file is closed. Other classes may make sure that that a socket or database connection is closed.
Combining the idea of using destructors for cleanup with stack based variables can be very powerful. For example, I can have a class that handles mutexes. When I create the object, the mutex is automatically locked. As soon as the scope the mutex is in is left, the mutex will be unlocked. I no longer have to worry about unlocking the mutex.
{ // begin mutual exclusion area
Mutex mutex(...);
...
do_stuff
...
} // mutex automatically unlocked
Additionally, the combination of destructors and stack based variables makes the above code example exception safe. Under C++, every successfully created object on the stack will be destroyed during the stack unwinding process. So, even if an exception is thrown, the mutex will become unlocked.
Languages like Objective-C and Java do have "finally" blocks that ensure code will be executed even though an exception is thrown. However, I consider this to be a much weaker method than destructors. With destructors, I need to write the cleanup code in exactly one place. With finally blocks, I must still write the cleanup code every time I use a class that requires cleanup.
In closing, I have but to say that I have found that destructors allow me to greatly simplify many parts of my code. And with code simplification comes ease of maintenance. And that is a wonderful thing.
