मैं इस प्रश्न का उत्तर देने जा रहा हूं (2 साल बाद) शेयर्ड_प्ट्र के एक बहुत ही सरलीकृत कार्यान्वयन का उपयोग करके जो उपयोगकर्ता समझेगा।
सबसे पहले मैं कुछ साइड क्लासेस, share_ptr_base, sp_counted_base sp_counted_impl, और check_deleter के अंतिम भाग में जा रहा हूँ, जिनमें से एक टेम्पलेट है।
class sp_counted_base
{
public:
sp_counted_base() : refCount( 1 )
{
}
virtual ~sp_deleter_base() {};
virtual void destruct() = 0;
void incref(); // increases reference count
void decref(); // decreases refCount atomically and calls destruct if it hits zero
private:
long refCount; // in a real implementation use an atomic int
};
template< typename T > class sp_counted_impl : public sp_counted_base
{
public:
typedef function< void( T* ) > func_type;
void destruct()
{
func(ptr); // or is it (*func)(ptr); ?
delete this; // self-destructs after destroying its pointer
}
template< typename F >
sp_counted_impl( T* t, F f ) :
ptr( t ), func( f )
private:
T* ptr;
func_type func;
};
template< typename T > struct checked_deleter
{
public:
template< typename T > operator()( T* t )
{
size_t z = sizeof( T );
delete t;
}
};
class shared_ptr_base
{
private:
sp_counted_base * counter;
protected:
shared_ptr_base() : counter( 0 ) {}
explicit shared_ptr_base( sp_counter_base * c ) : counter( c ) {}
~shared_ptr_base()
{
if( counter )
counter->decref();
}
shared_ptr_base( shared_ptr_base const& other )
: counter( other.counter )
{
if( counter )
counter->addref();
}
shared_ptr_base& operator=( shared_ptr_base& const other )
{
shared_ptr_base temp( other );
std::swap( counter, temp.counter );
}
// other methods such as reset
};
अब मैं make_sp_counted_impl नामक दो "फ्री" फंक्शन बनाने जा रहा हूं, जो एक पॉइंटर को नए बनाए गए एक पर लौटाएगा।
template< typename T, typename F >
sp_counted_impl<T> * make_sp_counted_impl( T* ptr, F func )
{
try
{
return new sp_counted_impl( ptr, func );
}
catch( ... ) // in case the new above fails
{
func( ptr ); // we have to clean up the pointer now and rethrow
throw;
}
}
template< typename T >
sp_counted_impl<T> * make_sp_counted_impl( T* ptr )
{
return make_sp_counted_impl( ptr, checked_deleter<T>() );
}
ठीक है, ये दो कार्य आवश्यक हैं जैसे कि जब आप एक templated फ़ंक्शन के माध्यम से साझा करें, तो आगे क्या होगा।
template< typename T >
class shared_ptr : public shared_ptr_base
{
public:
template < typename U >
explicit shared_ptr( U * ptr ) :
shared_ptr_base( make_sp_counted_impl( ptr ) )
{
}
// implement the rest of shared_ptr, e.g. operator*, operator->
};
ध्यान दें कि यदि टी शून्य है और ऊपर यू आपके "परीक्षण" वर्ग है तो क्या होगा। यह Make_sp_counted_impl () को U के पॉइंटर के साथ कहता है, T को पॉइंटर नहीं। विनाश का प्रबंधन सभी यहां से किया जाता है। Share_ptr_base वर्ग प्रतिलिपि और असाइनमेंट आदि के संदर्भ के साथ संदर्भ की गिनती का प्रबंधन करता है। साझा किया गया साझा वर्ग ऑपरेटर ओवरलोड (->, * आदि) के प्रकार के उपयोग का प्रबंधन करता है।
इस प्रकार यद्यपि आपके पास साझा करने के लिए एक साझा_प्रति है, पर आप उस प्रकार के एक संकेतक का प्रबंधन कर रहे हैं जिसे आपने नए में पारित किया है। ध्यान दें कि यदि आप अपने पॉइंटर को एक शून्य * में परिवर्तित करते हैं, तो इसे share_ptr में डालने से पहले, यह check_delete पर संकलित करने में विफल हो जाएगा, इसलिए आप वास्तव में वहां भी सुरक्षित हैं।