Re: smart pointer / constructor design problem
Andrew Tomazos schrieb:
I have a standard reference counted smart pointer class abridged as
follows:
class Handleable { int refs; }
template<T> // T is subclass of Handleable
class Handle<T>
{
T* m_p;
Handle(T* p) : m_p(p) { m_p->refs++; }
Handle(Handle<T>& that) : m_p(that.m_p) { m_p->refs++; }
Handle(Handle<T> const& that) /*...*/
....unless you don't want to initialize a Handle from a temporary.
~Handle() { if (m_p->refs-- == 0) delete this; }
I hope that this is a typo and you wanted to delete m_p here.
Also, it should be prefix decrement:
if (--m_p->refs == 0) delete m_p;
}
(Handle also can deal with null pointers and other things but you get
the idea)
The problem is that if a Handle is created and destroyed during
construction of a Handleable object, than the ref count is reduced to
0 and "delete this" fires:
void f(Handle<C> c)
{
...
}
class C : public Handleable
{
C()
{
f(this);
}
}
Handle<C> c = new C(); // crash, f's Handle<C> parameter causes
destruction of C instance before c's constructor can increment ref
count.
That's because a class' constructor shouldn't pass around smart pointers
of itself. The constructor's job is to initialize the class instance,
and not to start a thread or to pass the instance to a function that
uses it.
If you'ld write a class D that inherits from C, C's constructor would
pass the instance to a function even before D is fully constructed.
The creator, the one who does "new C", should be responsible for passing
the instance around:
Handle<C> c = new C;
f(c);
You can put this in a factory-like function and make the constructor
protected, if you want to enforce a call to f() for every instance of C.
--
Thomas
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]