开发者

how boost::~shared_ptr works?

when reading "Beyond the C++ Standard Library: An Introduction to Boost " ,I got a very interesting example:

class A  
{  
public:  
    virtual void sing()=0;  
protected:  
    virtual ~A() {};  
};

clas开发者_StackOverflow社区s B : public A
{  
public:  
    virtual void sing(  )  
    {  
       std::cout << "Do re mi fa so la"<<std::endl;;  
    }  
};  

and I do some testing:

int main()
{  

//1  
std::auto_ptr<A> a(new B); //will not compile ,error: ‘virtual A::~A()’ is protected

//2
A *pa = new B;
delete pa;  //will not compile ,error: ‘virtual A::~A()’ is protected
delete (dynamic_cast<B*>(pa)); //ok

//3 
boost::shared_ptr<A> a(new B);//ok

}

what I am very curious here is how ~shared_ptr works? how it deduce the derived class B ?

Thanks advance for your help!

thanks all, I write a simple sample about how ~shared_ptr works

class sp_counted_base
{
public:
    virtual ~sp_counted_base(){}
};

template<typename T>
class sp_counted_base_impl : public sp_counted_base
{
public:
    sp_counted_base_impl(T *t):t_(t){}
    ~sp_counted_base_impl(){delete t_;}
private:
    T *t_;
};


class shared_count
{
public:
    static int count_;
    template<typename T>
    shared_count(T *t):
        t_(new sp_counted_base_impl<T>(t))
    {
        count_ ++;
    }
    void release()
    {
        --count_;
        if(0 == count_) delete t_;
    }
    ~shared_count()
    {
        release();
    }
private:
    sp_counted_base *t_;
};
int shared_count::count_(0);

template<typename T>
class myautoptr
{
public:
    template<typename Y>
    myautoptr(Y* y):sc_(y),t_(y){}
    ~myautoptr(){ sc_.release();}
private:
    shared_count sc_;
    T *t_;
};

int main()
{
    myautoptr<A> a(new B);
}

the key is:

  1. template construct function
  2. the resource not deleted in ~shared_ptr ,it is deleted by shared_count


Surprisingly, the key here is not boost::shared_ptr destructor but its constructor(s).

If you look into boost/shared_ptr.hpp, you will see that shared_ptr<T> does not 'simply' have a constructor expecting a T * but :

template<class Y>
explicit shared_ptr( Y * p );

In //3 when you construct a boost::shared_ptr from a B *, no conversion to A * takes place, and the shared_ptr internals are built with the actual B type. Upon destruction of the object, deletion occurs on a B pointer (not through a base class pointer).


The shared_ptr class template has a member of class type shared_count, which in turn has a member of type pointer to class sp_counted_base. The constructor template for class shared_count assigns a pointer to an instance of the class template sp_counted_impl_p to this member which is templated by the type of the constructor argument, not by the shared_ptr::value_type. sp_counted_base has a pure virtual member function dispose which is overwritten by sp_counted_impl_p. Because sp_counted_impl_p knows the type B in your example, it can delete it without access to the base class destructor, and because it uses virtual dispatch, the type is determined at runtime. This method requires a combination of parametric and subtype polymorphism.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜