I've received some C++ code with various structures defined like this:
typedef struct _someStruct_ {
std::string someString;
std::vector<std::string> someVectorOfStrings;
int someOtherStuff;
~_someStruct_()
{
someString.clear();
someVectorOfStrings.clear();
}
} someStruct;
Is the destructor here completely redundant - if the structure were to be destructed by the default destructor, won't any strings, vectors, etc. be destructed anyway?
If I'd written the code, I wouldn't have thought of adding an explicit destructor here - I'd just let the compiler get on with it.
As I understand it, the only time you might need to create your own destructor in a struct is if any of the members of the structures contain pointers to data that might need cleaning up, or if some extra functionality (e.g. for debugging, logging when a structure gets deleted) is needed.
Am I missing something here - is there any reason why strings and vectors have been explicitly cleared in the destructor? My suspicion is that the person who sent me this is really a C programmer (cf. the typedef) who's tried to turn some C code into C++.
Destructors are usually used to deallocate memory and do other cleanup for a class object and its class members when the object is destroyed. A destructor is called for a class object when that object passes out of scope or is explicitly deleted.
When delete is used to deallocate memory for a C++ class object, the object's destructor is called before the object's memory is deallocated (if the object has a destructor). If the operand to the delete operator is a modifiable l-value, its value is undefined after the object is deleted.
A destructor is a member function that is invoked automatically when the object goes out of scope or is explicitly destroyed by a call to delete . A destructor has the same name as the class, preceded by a tilde ( ~ ).
The object would be destroyed automatically and the destructor would be called as the object went out of scope when foo returns.
Yes, the destructor is completely redundant.
As you’ve said yourself the code has other warnings signs. Using typedef struct
for instance makes no sense whatsoever in C++, it’s as redundant as the empty destructor: The code was written by somebody with a marginal grasp of C++, there are bound to be more gotchas (for one thing, the class name is invalid due to the leading underscore in global scope).
In fact, this is worse than simply using the implicit destructor.
By having the explicit destructor, the compiler will not provide an implicit move constructor for you!
The destructor is almost completely redundant.
It does three things.
First, it blocks the automatic creation of copy/move constructors and assignment. This ... may not be a good thing. But maybe it is desired. It is, however, not the same as not being there.
Second, it changes the order the stuff is cleaned up in. The buffer held by the string is cleared, then each buffer held by the strings in the vector are destroyed while the string holding them are destroyed, then the vector with a buffer of unused memory is destroyed (returning the memory), then the now empty string is destroyed.
With a default destructor, the order is the vector's string's buffers are destroyed, then the memory for the vector's strings is returned while the vector is destroyed, then the string is destroyed along with its buffer being returned.
You could possible detect this with suitable overloads to operator new
& delete
, or if you used custom allocators.
Finally, such destructors can sometimes be easier to debug, as you can step through them.
The odds are, however, that none of these subtle effects where intended by the developer who wrote that code.
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