Boost logo

Boost :

From: Howard Hinnant (hinnant_at_[hidden])
Date: 2008-07-16 17:31:18


On Jul 16, 2008, at 4:51 PM, Mathias Gaunard wrote:

> "I personally don't see the point in dynamic deleters, they're only
> specializations of static ones."

The advantage is that instead of doing this:

struct B;

class A
{
public:
    typedef std::unique_ptr<B, void(*)(B*)> handle;
private:
    handle p_;
public:
    static void reclaim(B*); // used as the deleter

    A(); // p_ constructed with reclaim
    handle get() {return std::move(p_);}
};

int main()
{
    A a;
    A::handle p = a.get();
    // ...
} // call A::reclaim(p.get())

one could do this:

struct B;

class A
{
    shared_ptr<B> p_;
public:
    static void reclaim(B*); // used as the deleter

    A(); // p_ constructed with reclaim
    shared_ptr<B> get() {return p_;}
};

int main()
{
    A a;
    shared_ptr<B> p = a.get();
    // ...
} // call A::reclaim(p.get())

The difference is that you don't have to use A::handle to mask your
smart pointer type. You can advertise that shared_ptr<B> will be your
smart pointer type. When you do so, you still leave yourself the
freedom to change your destruction policy in the future without
disturbing API or ABI. However recall that in the first case you can
change your destruction policy by simply rewriting A::reclaim(B*)
without disturbing API or ABI as well.

The difference here is subtle, and some may even say insignificant.
Others will say very significant. If the client of A also has a
client C that uses the smart_ptr of A then the closer you can come to
a "common well known type" the better. shared_ptr<B> is better known
than unique_ptr<B, void(*)(B*)> or A::handle.

It is good to have all of these tools in the toolbox: shared_ptr,
unique_ptr, scoped_ptr. There are different situations where each one
is best.

Disclaimer: I currently don't have a good use case for scoped_ptr.
But people I highly respect say they do and that's good enough for me.

Note: I believe the more important difference between shared_ptr and
unique_ptr is the copy vs move characteristic as opposed to the static
vs dynamic deleter characteristic. shared_ptr is better suited to
handle dynamic deleters because it is already committed to auxiliary
heap storage to store the reference count and so can handle the
dynamic deleter with nearly zero extra overhead. The same isn't true
of unique_ptr. One should generally choose between shared_ptr and
unique_ptr based on whether you want copy or shared-ownership
semantics vs unique-ownership/move-only semantics. Neither of these
choices is universally better than the other (despite the design of
some other languages ;-) ).

-Howard


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