C++ stack allocated object, explicit destructor ca

2019-03-28 13:49发布

问题:

I came across a strange use of the destructor while working on an existing library. The destructor of a stack allocated stl vector was being called explicitly, when its the case that that object may need to be used again. These vector objects are a slightly customised version of the stl vector class that have a specialized clear method. In the destructor body there exist two method calls: clear(), _Tidy().

I've been trying to think of a good reason why this destructor is being called rather than just clear but I'm at a loss. Anyone shed any light on why this may be a good idea?

回答1:

clear() isn't guaranteed to actually release the allocated storage in the vector; _Tidy() in the MSVC implementation will actually free that storage, so this was probably done as an optimization.

It's an evil thing to do, but you can do it legally (without undefined behavior) so long as the storage is reused by an object of the same type (ignoring cv-qualifiers) that takes up exactly all of the storage:

T automatic;
automatic.T::~T();
new (&automatic) T();

Section 3.8.7 of the C++ standard describes this usage scenario and explains how it's legal; it even includes an example that is similar to the above.



回答2:

Could this class use some kind of placement new method? That's the only time I tend to see explicit destructors in use.



回答3:

Large vector?

Wild guess... when clear() is called the vector is usually emptied but the memory not released. That is why there's the pattern

std::vector<T>().swap(vector_to_clear);

to empty the vector for reuse and clear the allocated memory.

Perhaps the original author did not know the pattern and tried to get rid of the allocated memory in this wicked fashion. (I think _Tidy frees the allocated memory)



回答4:

It's definitely not a good idea. Any operation on an object after the destructor starts running yields undefined behavior.



回答5:

Maybe the original coder cared about where in memory the objects were allocated.

Then the destructor must be called explicitly, as per this discussion.