struct ref_counter //base (opaque) class for reference counting { int count; //reference counter variable ref_counter() : count(0) //instance is not referenced yet {} void ref() //add reference { ++count; return; } int deref() //remove reference { return --count; } }; template struct safe_deleter; //forward declaration template struct ptr_base //implementation detail class { type *data; //here data pointer is stored ptr_base() : data(0) //no data yet {} void detach() //does what it says { if (data && data->deref()==0) //if ref counter drops to zero delete data; //deleting data data = 0; //finally detached return; } }; template struct ptr : ptr_base //shared pointer class { ptr() //constructors {} ptr(const ptr &other) { attach(other.data); } ptr(type *p) { attach(p); } ~ptr() //destructor { detach(); } ptr &operator=(const ptr &other) //asignment operators { attach(other.data); return *this; } ptr &operator=(type *p) { attach(p); return *this; } operator const safe_deleter*() const; //here the magic is (defined below) void attach(type *p) //does what it says { p->ref(); //now we hold a reference to the data detach(); //detaching from old data data = p; //finally attached return; } }; template struct safe_deleter : ptr_base {//ptr_base has trivial destructor which does nothing (just what we need) void operator delete(void *p) //overloaded scalar delete operator { reinterpret_cast(p)->detach(); //detaching from data return; } }; template inline ptr::operator const safe_deleter*() const //here magic happens { if (!data) //if pointer is invalid return 0; //return null pointer const ptr_base *base = this; //trivial and fully legal conversion return static_cast*>(base); //oops! a little hack... } #include //user code from here //#include #include using namespace std; struct arbitrary_type : public ref_counter {//arbitrary type must inherit 'ref_counter' int i; arbitrary_type(int v = 1234567890) : i(v) { cout << " arbitrary_type(" << i << ") constructed\n"; } ~arbitrary_type() { cout << " arbitrary_type(" << i << ") destructed\n"; } }; #define COUNT(p) { cout << " '" << #p << "' ref count = " << (p.data ? p.data->count : 0) << "\n"; } (void)0 #define STATEMENT(s) { cout << #s << "\n"; } s { COUNT(p); COUNT(q); cout << "\n"; } int main() { { ptr p = new arbitrary_type(1), q; COUNT(p); COUNT(q); cout << "\np is " << (p ? "valid" : "invalid") << "\nq is " << (q ? "valid" : "invalid") << "\np&&q is " << (p && q ? "true" : "false") << "\np||q is " << (p || q ? "true" : "false") << "\n\n"; STATEMENT(q = p;) STATEMENT(delete q;) //TA-DA!!! assert(p); assert(!q); STATEMENT(q = new arbitrary_type(2);) STATEMENT(p = q;) cout << "out of scope\n"; } //_getch(); return 0; }