// ========================================================================== // $Id: smart_pointer.hh,v 1.3 2006/11/20 04:52:11 jlang Exp $ // CSI2372 example Code for lecture 13 // ========================================================================== // (C)opyright: // // Jochen Lang // SITE, University of Ottawa // 800 King Edward Ave. // Ottawa, On., K1N 6N5 // Canada. // http://www.site.uottawa.ca // // Creator: jlang (Jochen Lang) // Email: jlang@site.uottawa.ca // ========================================================================== // $Log: smart_pointer.hh,v $ // Revision 1.3 2006/11/20 04:52:11 jlang // Check-in for lecture 13 // // Revision 1.2 2006/11/19 22:53:31 jlang // Smart pointer example with ref-count // // Revision 1.1 2006/11/19 18:30:50 jlang // Added smart pointer -- not compiled // // // ========================================================================== #ifndef SMART_PTR_HH_ #define SMART_PTR_HH_ #include #include /** * Smart pointer class implementing refrence counting * partially based on A. Alexandrescu, Modern C++ Design, Chpt. 7 */ template class SmartPtr { /** Helper class for reference counter */ class RefCounter { unsigned int d_pCount; public: RefCounter() : d_pCount(1){}; void clone() { ++d_pCount; return; } bool release() { if (!--d_pCount) { return true; } return false; } }; class Tester { void operator delete(void *); }; // The object pointed to T* d_pointee; RefCounter* d_counter; public: // constructor from native pointer - do not allow null explicit SmartPtr( T* _pointee ) : d_pointee(_pointee), d_counter(new RefCounter()) { if (d_pointee == 0) { delete d_counter; throw std::runtime_error("Smart pointer cannot be null"); } } // copy constructor from other smart pointer SmartPtr(SmartPtr& _src) // share the object and the reference counter : d_pointee(_src.d_pointee), d_counter(_src.d_counter) { d_counter->clone(); // increase the counter } // delete this smart pointer ~SmartPtr() { // decrease ref count and check if we are the last pointer to object if ( d_counter->release() ) { delete d_pointee; // delete object delete d_counter; // delete counter object } } // assign an smart ptr to this smart ptr SmartPtr& operator=(const SmartPtr& _src) { if (this != &_src) { // decrease ref count and check if we are the last pointer to object if ( d_counter->release() ) { delete d_pointee; // delete object delete d_counter; // delete counter object } // assign the object and ref. counter from _src d_counter = _src.d_counter; d_counter->clone(); d_pointee = _src.d_pointee; } return *this; } // get the object T& operator*() { return *d_pointee; } // get the pointer to be used in -> operator T* operator->() { return d_pointee; } /*------------------------------------------------- * Member functions which expose d_pointee *------------------------------------------------*/ // Get at the object pointer T* GetImpl() { return d_pointee; } // Get at the address of the object pointer T*& GetImplRef() { return &d_pointee; } // Reset this smart pointer to point to source void reset(T* _src) { // decrease ref count and check if we are the last pointer to object if ( d_counter->release() ) { delete d_pointee; // delete object delete d_counter; // delete counter object } d_pointee = _src; d_counter = new RefCounter(); if (d_pointee == 0) { delete d_counter; throw std::runtime_error("Smart pointer cannot be null"); } } // Release this smart pointer and set dest to pointee // - not consistent with non-zero pointer policy // void release(T*& _dest) { // _dest = d_pointee; // d_pointee = 0; // if ( d_counter->release() ) { // delete d_counter; // delete counter object // } // } /*------------------------------------------------- * Operators for comparison *------------------------------------------------*/ // if (!ptr) -- redundant here since d_pointee is never 0 bool operator!() const { return d_pointee == 0; } // if ( sPtrA == ptrB ) ... inline bool operator==(const T *rhs ) { return d_pointee == rhs; } // if ( ptrA == sPtrB ) ... inline friend bool operator==( const T *lhs, const SmartPtr& rhs) { return lhs == rhs.d_pointee; } // if ( sPtrA != ptrB ) ... inline bool operator!=(const T *rhs ) { return d_pointee != rhs; } // if ( ptrA != sPtrB ) ... inline friend bool operator!=( const T *lhs, const SmartPtr& rhs) { return lhs != rhs.d_pointee; } // Enable equal comparison in class hierarchies template bool operator==( const U* rhs ) { return d_pointee == rhs; } template inline friend bool operator==( const U* rhs, const SmartPtr& lhs ) { return rhs == lhs.d_pointee; } // Enable not equal comparison in class hierarchies template bool operator!=( const U* rhs ) { return d_pointee != rhs; } template inline friend bool operator!=( const U* rhs, const SmartPtr& lhs ) { return rhs != lhs.d_pointee; } // comparison with another smart pointer template bool operator==( const SmartPtr& rhs ) const { return d_pointee == rhs.d_pointee; } template bool operator!=( const SmartPtr& rhs ) const { return d_pointee != rhs.d_pointee; } // conversion operator to Tester // this will enable if (smartPtr) // -- redundant here since d_pointee is never 0 operator Tester*() const { if (!d_pointee ) return 0; static Tester test; return &test; } }; #endif