Boost logo

Boost :

From: hollp (hollp_at_[hidden])
Date: 2002-04-18 10:31:12


Here Here! Me too! I also have stayed away from shared_ptr for many of the
reasons listed below.

Some other advantages of intrusive reference counting:

- smart pointer implementation becomes much simpler than shared_ptr - no
worries about exception safety because you can safely assume that AddRef and
Release do not throw (I can't think of any implementations that would need to
be able to throw exceptions). This is also a consequence of the fact that the
memory allocation is done in a single step rather than the reference count
being kept separately.
- smart pointer implementation doesn't need to worry about thread safety -
this is up to how AddRef/Release are implemented
- It's often useful to be able to implement addRef and release
polymorphically. For example, contained objects can forward the methods to
their parent object rather than keeping a separate reference count themselves
(this is often a useful way around the "circular reference" problem):

// Wheel object knows that it is owned by Car object
class Wheel
{
   Car *car_;
   void AddRef() { car_->AddRef(); }
   void Release() { car_->Release(); }
   RefPtr<Car> getCar() { return car_; }
   // etc.
}

The key advantage is that the object itself gets to decide where the memory it
uses comes from - which is essential for instances that come from different
DLLs (as he said).

One possible disadvantage is that you do have to decide up front whether your
object is to be thread safe, which I believe Herb Sutter/Jim Hyslop have said
is the wrong division of responsibilities:
"The third, like it, is this: Thou shalt not make objects thread-safe; it is a
perversion. "
- http://www.cuj.com/experts/2004/hyslop.htm?topic=experts.

Anyway, on WIN32 the overhead of this particular thread safe implementation
usually isn't much of an issue because InterlockedIncrement/Decrement are very
efficient.

Of course, I too am biased by my COM background ;-) I just wanted to add my
vote to the pool of people saying that shared_ptr is not enough.

Paul
http://PaulHollingsworth.com

>A couple of comments: I, like you, need to create smart pointers from this
>frequently, and I also dislike the separate allocation of the reference
>count. In fact, I've stayed away from boost::shared_ptr entirely for those
>reasons & instead rolled my own intrusive ref-counted pointer several times.
>
>One thing I'd change, although this does come with a cost, is to make the
>objects self-deleting. This requires making the destructor of ref_counted
>virtual, and putting a "delete this;" in ref_counted::release(). I know
>some (many?) people dislike this idiom because 'delete this' feels so wrong,
>but it's actually a very good idiom, especially in environments where it's
>possible to have multiple heaps in a single program. In such situations,
>it's essential that the delete expression use the heap from which the object
>was created. To complete the pattern, I always use a factory (function,
>class, whatever) with such classes, and make both the constructor(s) and
>destructor private.
>
>Maybe it's just my COM background influencing me... but this strategy has
>worked very well for me in many large projects.
>
>-cd
>


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk