Using boost::shared_ptr on class hierarchies
boost::shared_ptr has become one of the most versatile smart_pointer structures used in C++.
If you consistently use shared_ptr to refer to objects,
you don’t have to worry when to destroy them.
We would like to see how boost::shared_ptr can be used amidst up-casting and down-casting across class hierarchies.
Consider the following class.
class A
{
public:
A():m_i(0){}
virtual ~A(){}
int m_i;
};
If we always use boost::shared_ptr-s to refer to an instance of A, we
can use them across scopes, worry free of when to destroy them as shown.
using namespace boost;
shared_ptr <A> sA1;
{
shared_ptr <A> sA2( new A);
sA1 = sA2;
//sA1 and sA2 shares the same pointer to A
//and the same reference counting structure
assert( sA1.use_count() == sA2.use_count() );
assert( sA1.use_count() == 2);
}
assert( sA1.use_count() == 1);
Now, let B, be a derived class of A as shown below.
</pre> class B : public A { public: B():m_j(0){} ~B(){} int m_j; }; </pre>
shared_ptr and up-casting
If we assign a shared_ptr B to a shared_ptr A,
the two shared pointers still share the same pointer and the reference count. So shared_pointer respects up-casting. Please see the code below.
using namespace boost;
shared_ptr <A> sA;
{
shared_ptr <B> sB( new B);
sA = sB;
//sA and sB shares the same pointer to B
//and the same reference counting structure
assert( sA.use_count() == sB.use_count() );
assert( sA.use_count() == 2);
}
assert( sA.use_count() == 1);
shared_ptr and down-casting
Now consider the problem of down-casting.
using namespace boost;
shared_ptr <B> sB;
{
shared_ptr <A> sA( new B);
//how can we reset sB with the pointer
//now owned by sA.?
}
The following wont compile.
using namespace boost;
shared_ptr <B> sB;
{
shared_ptr <A> sA( new B);
//compilation error in the line below
sB = sA;
}
Here is another wrong way, that results in run-time error.
using namespace boost;
shared_ptr <B> sB;
{
shared_ptr <A> sA( new B);
B * pB = dynamic_cast <B*> (sA.get());
sB.reset( pB );
//though sA and sB now points to the same
//instance of B, they are reference counted
//using different structures.
assert( sA.use_count() == 1);
assert( sB.use_count() ==1);
}
//Instance of B pointed to by sA is destroyed.
//But hey, sB still refers to it.
//Now, the following will cause a runtime error
//due to double deletion
sB.reset();
The correct way is shown below.
using namespace boost;
shared_ptr <B> sB;
{
shared_ptr <A> sA( new B);
sB = dynamic_pointer_cast <B,A> ( sA ) ;
//sA and sB now shares the same instance of B.
//Further sA and sB shares the same reference
//counting structure.
assert( sA.use_count() == 2);
assert( sB.use_count() == 2);
}
assert( sB.use_count() == 1);
blog comments powered by Disqus