From c++ FAQ: http://www.parashift.com/c++-faq-lite/dtors.html#faq-11.9
Remember: delete p does two things: it calls the destructor and it deallocates the memory.
If delete deallocates the memory, then what's the need of the destructor here?
If delete deallocates the memory, then what's the need of the destructor here?
The point of the destructor is to execute any logic required to clean up after your object, for example:
You need to call the destructor in case there are other things that need to be done other than just de-allocating memory.
Other than very simple classes, there usually are.
Things like closing file handles or shutting down database connections, deleting other objects that are pointed to by members data within your object, and so forth.
A classic example is the implementation of a stack:
class myStack {
private:
int *stackData;
int topOfStack;
public:
void myStack () {
topOfStack = 0;
stackData = new int[100];
}
void ~myStack () {
delete [] stackData;
}
// Other stuff here like pop(), push() and so on.
}
Now think of what would happen if the destructor was not called every time one of your stacks got deleted. There is no automatic garbage collection in C++ in this case so the stackData
memory would leak and you'd eventually run out.
This requiring of a destructor to delete all its resources moves down the tree towards the basic types. For example, you may have a database connection pool with an array of database connections. The destructor for that would delete
each individual database connection.
A single database connection may allocate a lot of stuff, such as data buffers, caches, compiled SQL queries and so on. So a destructor for the database connection would also have to delete
all those things.
In other words, you have something like:
+-------------------------------------+
| DB connection pool |
| |
| +-------------------------+---+---+ |
| | Array of DB connections | | | |
| +-------------------------+---+---+ |
| | | |
+-----------------------------|---|---+
| | +---------+
| +-> | DB Conn |
+---------+ | +---------+
| DB Conn | <----+ / | \
+---------+ buffers | queries
/ | \ caches
buffers | queries
caches
Freeing the memory for the DB connection pool would not affect the existence of the individual DB connection or the other objects pointed to by them.
That's why I mentioned that only simple classes can get away without a destructor, and those are the classes that tend to show up at the bottom of that tree above.
A class like:
class intWrapper {
private:
int value;
public:
intWrapper () { value = 0; }
~intWrapper() {}
void setValue (int newval) { value = newval; }
int getValue (void) { return value; }
}
has no real need for a destructor since the memory deallocation is all you need to do.
The bottom line is that new
and delete
are opposite ends of the same pole. Calling new
first allocates the memory then calls the relevant constructor code to get your object in a workable state.
Then, when you're done, delete
calls the destructor to "tear down" your object the reclaims the memory allocated for that object.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With