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:
- template construct function
- 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.
精彩评论