Over a year ago, during the work on the various resource managers, I was unpleasantly startled by the behaviour of STL containers. To present how does the matter of problem stand, it would be the best to include some piece of code:
class Clonable
{
public:
virtual ~Clonable ();
virtual Clonable* clone () const; // Virtual constructor
};
class Referable : public Clonable
{
private:
int nref; // Reference counter
...
public:
...
virtual ~Referable ();
virtual Referable* clone () const;
...
template<typename T> friend class SmartPtr;
};
template<typename T> // T must be the type of public Referable class
class SmartPtr
{
public:
...
SmartPtr (const SmartPtr<T>& sp); // Copy constructor
...
SmartPtr<T>& operator= (const SmartPtr<T>& sp); // Assigment operator
...
};
As it is seen, the code above defines the invasive smart pointer class and pointer-base class, which derivates could be referred by SmartPtr. It's needless to say, that SmartPtr methods do little more than a simple assigment, whereas it operates on reference counter. Thus the proper work of SmartPtr class and it's references is sustained only by the usage of class' internal methods.
This code should work correctly:
class Actor : public Referable
{
...
public:
void play ();
}
...
int main (int argc, char* argv[])
{
SmartPtr<Actor> p1(new Actor(...)), p2(new Actor(...));
p2 = p1;
p1.release();
p2->play();
p2->release();
// No memory leaks
...
}
It would be fine if I could create a deque (or vector, list, map or even AVL tree) of smart pointers; unfortunately the followind code doesn't work correctly:
...
std::deque<SmartPtr<Actor> > actors;
actors.push_back(new Actor(...)); // Implicit conversion from Actor* to SmartPtr<Actor> is supported by SmartPtr<T>::SmartPtr(T*)
...
actors.clear(); // Does not call virtual destructor Actor::~Actor, so actor's nref will never reach 0 and object won't be destroyed
// Memory heap still contains object Actor
The implementation of std::deque (and other containers) uses memcpy() function instead of operator= method and copy constructor (I've checked VC++ 6.0 and portable-STL implementations). I ommit those circumstances by implementing a disting class SmartPtrDeque, but it's not a solution (which seems proper).
So my question is: Is it possible to force STL containers to treat it's data as objects, not structures 