views:

471

answers:

5

Hi,

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  A: 

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

Jurily
Or rather, after the destructor finishes? I suppose it might be valid if you construct another instance at the same place with placement new before doing anything else with the instance and before it goes out of scope.
UncleBens
And these operations include the dtor being automatically invoked at the end of the scope.
sbi
@UncleBens: no, as soon as the destructor starts you should consider your object no longer exists... try using virtual functions from a destructor of a base class that actually use a heap-allocated memory of the derived class... see what I mean :) ?
Matthieu M.
+5  A: 

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

the_mandrill
Beat me to the punch while I was writing. ;)
John at CashCommons
+1  A: 

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

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

John at CashCommons
Which is probably the case since the discussion is about a stack-allocated vector.
Matthieu M.
+4  A: 

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)

Rüdiger Hanke
The vectors vary in size but none eroneously large.I would love to know the original authors intent on this, and hopefully it was just a misguided memory deallocation
Colin
My first question is such situations is: What's the checkin comment?
sbi
+7  A: 

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.

Josh Petrie