Listing 4
// a simple reference counted UN-smart pointer #ifndef NDEBUG template<typename T> struct counted_ptr { counted_ptr(const new_ptr<T>& x) : mp(x.m), ref_count(new int(1)) { } counted_ptr() : mp(NULL), ref_count(NULL) { } bool operator==(const counted_ptr& x) const { return mp == x.mp; } bool operator!=(const counted_ptr& x) const { return mp != x.mp; } ~counted_ptr() { Release(); } counted_ptr(const counted_ptr& x) { private_assign(x); } T* operator->() const { assert(mp != NULL); return mp; } T& operator*() const { assert(mp != NULL); return *mp; } operator const ptr<T, !deletable>&() { // only allows conversion to non-deletable pointers return mp; } void operator=(const counted_ptr& x) { if (*this == x) return; // change nothing Release(); private_assign(x); } void Release() { if (mp == NULL) return; assert(ref_count != NULL && "implementation error"); --(*ref_count); assert(*ref_count > 0 && "orphaning memory"); mp = NULL; } void Delete() { if (mp == NULL) { assert(ref_count == NULL && "implementation error"); return; } assert(ref_count != NULL && "implementation error"); assert(*ref_count == 1 && "can not delete when other references still remain"); delete ref_count; delete mp; mp = NULL; } static counted_ptr Null() { return counted_ptr(); } private: void private_assign(const counted_ptr& x) { // private, because it is unsafe. The public methods // make sure everything is kosher mp = x.mp; ref_count = x.ref_count; if (mp != NULL) { assert(ref_count != NULL && "implementation error"); ++(*ref_count); } else { assert(ref_count == NULL && "implementation error"); } } private: T* mp; int* ref_count; }; #else template<typename T> struct counted_ptr { counted_ptr(const new_ptr<T>& x) : mp(x.m) { } counted_ptr() : mp(NULL){ } bool operator==(const counted_ptr& x) const { return mp == x.mp; } bool operator!=(const counted_ptr& x) const { return mp != x.mp; } counted_ptr(const counted_ptr& x) { mp = x.mp; } T* operator->() const { return mp; } T& operator*() const { return *mp; } operator const ptr<T, !deletable>&() { return mp; } void operator=(const counted_ptr& x) { mp = x.mp; } void release() { mp = NULL; } void Delete() { delete mp; mp = NULL; } static counted_ptr null() { return counted_ptr(); } }; #endif