首先来看SmartPtr的定义:
#include < assert.h >
///
// a simple smart pointer wrapper class, use reference count
///
template < class T > class SmartPtr
{
public :
// Construction and destruction
SmartPtr(T * p = 0 );
~ SmartPtr();
// Copying and assignment
SmartPtr( const SmartPtr < T >& sp);
SmartPtr < T >& operator = ( const SmartPtr < T >& sp);
// Dereferencing
T * operator -> () const ;
T & operator * () const ;
// implicit cast from SmartPtr to native ptr
// advantage: can use SmartPtr as the native ptr everywhere. (parameter pass, equality test...)
// disadvantage: dangerious, because client might delete this pointer by accident
operator T * () const ;
private :
void AddRef();
void Release();
T * m_pRef;
unsigned int * m_pRefCount;
};
///
// Construction and destruction
///
template < class T > SmartPtr < T > ::SmartPtr(T * p):m_pRef(p),m_pRefCount( 0 )
{
AddRef();
}
template < class T > SmartPtr < T > :: ~ SmartPtr()
{
Release();
}
// Copying and assignment
template < class T > SmartPtr < T > ::SmartPtr( const SmartPtr < T >& sp)
{
m_pRef = sp.m_pRef;
m_pRefCount = sp.m_pRefCount;
AddRef();
}
template < class T > SmartPtr < T >& SmartPtr < T > :: operator = ( const SmartPtr < T >& sp)
{
if ( * this != sp)
{
Release();
m_pRef = sp.m_pRef;
m_pRefCount = sp.m_pRefCount;
AddRef();
}
return * this ;
}
// Dereferencing
template < class T > T * SmartPtr < T > :: operator -> () const
{
assert(m_pRef);
return m_pRef;
}
template < class T > T & SmartPtr < T > :: operator * () const
{
assert(m_pRef);
return * m_pRef;
}
// implicit cast from SmartPtr to native ptr
// advantage: can use SmartPtr as the native ptr everywhere. (parameter pass, equality test...)
// disadvantage: dangerious, because client might delete this pointer by accident
template < class T > SmartPtr < T > :: operator T * () const
{
return m_pRef;
}
template < class T > void SmartPtr < T > ::AddRef()
{
if ( 0 == m_pRef) return ;
if ( 0 == m_pRefCount) {m_pRefCount = new unsigned int ( 0 ); }
( * m_pRefCount) ++ ;
}
template < class T > void SmartPtr < T > ::Release()
{
if ( 0 == m_pRefCount) return ;
if ( -- ( * m_pRefCount) == 0 )
{
delete m_pRefCount;
delete m_pRef;
}
}
{
public :
TestPtr( int * p): ptr(p) { }
~ TestPtr( ) { delete ptr; }
// other operations
private :
int * ptr;
// other data
};
{
friend class TestPtr;
int * ptr;
size_t count;
RefPtr ( int * p): ptr(p), count( 1 ) {}
~ RefPtr () {
delete ptr;
}
};
class TestPtr
{
public :
TestPtr( int * p): ptr( new RefPtr(p)) { }
TestPtr( const TestPtr & src): ptr(src.ptr) {
++ ptr -> count;
}
TestPtr & operator = ( const TestPtr & rhs) {
// self-assigning is also right
++ rhs.ptr -> count;
if ( -- ptr -> count == 0 )
delete ptr;
ptr = rhs.ptr;
return * this ;
}
~ TestPtr() {
if ( -- ptr -> count == 0 )
delete ptr;
}
private :
RefPtr * ptr;
};
当希望每个TestPtr对象中的指针所指向的内容改变而不影响其它对象的指针所指向的内容时,可以在发生修改时,创建新的对象,并修改相应的引用计数。这种技术的一个实例就是写时拷贝(Copy-On-Write)。
#include < iostream >
#include < stdexcept >
using namespace std;
#define TEST_SMARTPTR
class Stub
{
public :
void print() {
cout << " Stub: print " << endl;
}
~ Stub(){
cout << " Stub: Destructor " << endl;
}
};
template < typename T >
class SmartPtr
{
public :
SmartPtr(T * p = 0 ): ptr(p), pUse( new size_t( 1 )) { }
SmartPtr( const SmartPtr & src): ptr(src.ptr), pUse(src.pUse) {
++* pUse;
}
SmartPtr & operator = ( const SmartPtr & rhs) {
// self-assigning is also right
++* rhs.pUse;
decrUse();
ptr = rhs.ptr;
pUse = rhs.pUse;
return * this ;
}
T * operator -> () {
if (ptr)
return ptr;
throw std::runtime_error( " access through NULL pointer " );
}
const T * operator -> () const {
if (ptr)
return ptr;
throw std::runtime_error( " access through NULL pointer " );
}
T & operator * () {
if (ptr)
return * ptr;
throw std::runtime_error( " dereference of NULL pointer " );
}
const T & operator * () const {
if (ptr)
return * ptr;
throw std::runtime_error( " dereference of NULL pointer " );
}
~ SmartPtr() {
decrUse();
#ifdef TEST_SMARTPTR
std::cout << " SmartPtr: Destructor " << std::endl; // for testing
#endif
}
private :
void decrUse() {
if ( --* pUse == 0 ) {
delete ptr;
delete pUse;
}
}
T * ptr;
size_t * pUse;
};
int main()
{
try {
SmartPtr < Stub > t;
t -> print();
} catch ( const exception & err) {
cout << err.what() << endl;
}
SmartPtr < Stub > t1( new Stub);
SmartPtr < Stub > t2(t1);
SmartPtr < Stub > t3( new Stub);
t3 = t2;
t1 -> print();
( * t3).print();
return 0 ;
}