Boost logo

Boost :

From: Phil Bouchard (philippe_at_[hidden])
Date: 2008-08-29 23:21:28


"Scott McMurray" <me22.ca+boost_at_[hidden]> wrote in message
news:fa28b9250808290914l19a6cf1fue658229148ec0f09_at_mail.gmail.com...

[...]

> It's not an allocator, and it's often useful in strange ways:
>
> shared_ptr<FILE> f( fopen("file.txt"), fclose );
>
> The fact that the deleter is specified on initialization is also
> essential in that it allows you to create shared_ptrs to incomplete
> types:
>
> struct S { auto_ptr<S> p; }; // illegal
> struct S { shared_ptr<S> p; }; // fine
>
> So I don't really see your point, here.

I think you're confusing the allocator and the deleter but I am exclusively
referring to the allocator. I just looked at the code of shared_ptr today
and it is very similar to what I wrote yesterday:

template<class P, class D, class A>
    class sp_counted_impl_pda: public sp_counted_base
    {
        ...
        virtual void destroy() // nothrow
        {
            typedef typename A::template rebind< this_type >::other A2;

            A2 a2( a_ );

            this->~this_type();
            a2.deallocate( this, 1 );
            // ugh!
        }
    };

This is ill-formed code. It's obvious shared_ptr is still in its
theoretical stage as far as the allocator is concerned; because
std::allocator is a bad example to start with. Let's take a real one like
the following:

// allocator
template <typename T>
    class my_allocator
    {
        boost::fast_pool_allocator pool_;
        ...
        void deallocate(pointer & p)
        {
            pool_.deallocate(p.release());
            // do not touch "this" anymore starting here!!
        }
    };

The way shared_ptr works right now, the pool is going to be copied entirely
on to the sp_counted_impl_pda object. The problem here is that the pool is
going to delete its own instance when deallocate() is called. The allocator
variable sp_counted_impl_pda::a_ will need to be changed for a functor or a
global function pointer before anything else.

Moreover using and allocator explicitly using release() saves some
unnecessary overhead for tested classes and library programmers. One might
wonder why using a smart pointer for well tested classes? Well it turns out
shifted_ptr is much more efficient this way because all node allocations
will be part of the same set.

-Phil


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