Mega Code Archive

 
Categories / C++ Tutorial / Data Types
 

Class for counted reference semantics

/* The following code example is taken from the book  * "The C++ Standard Library - A Tutorial and Reference"  * by Nicolai M. Josuttis, Addison-Wesley, 1999  *  * (C) Copyright Nicolai M. Josuttis 1999.  * Permission to copy, use, modify, sell and distribute this software  * is granted provided this copyright notice appears in all copies.  * This software is provided "as is" without express or implied  * warranty, and with no claim as to its suitability for any purpose.  */ #include <iostream> #include <list> #include <deque> #include <algorithm> using namespace std; /* class for counted reference semantics  * - deletes the object to which it refers when the last CountedPtr  *   that refers to it is destroyed  */ template <class T> class CountedPtr {   private:     T* ptr;        // pointer to the value     long* count;   // shared number of owners   public:     // initialize pointer with existing pointer     // - requires that the pointer p is a return value of new     explicit CountedPtr (T* p=0)      : ptr(p), count(new long(1)) {     }     // copy pointer (one more owner)     CountedPtr (const CountedPtr<T>& p) throw()      : ptr(p.ptr), count(p.count) {         ++*count;     }     // destructor (delete value if this was the last owner)     ~CountedPtr () throw() {         dispose();     }     // assignment (unshare old and share new value)     CountedPtr<T>& operator= (const CountedPtr<T>& p) throw() {         if (this != &p) {             dispose();             ptr = p.ptr;             count = p.count;             ++*count;         }         return *this;     }     // access the value to which the pointer refers     T& operator*() const throw() {         return *ptr;     }     T* operator->() const throw() {         return ptr;     }   private:     void dispose() {         if (--*count == 0) {              delete count;              delete ptr;         }     } }; void printCountedPtr (CountedPtr<int> elem) {     cout << *elem << ' '; } int main() {     // array of integers (to share in different containers)     static int values[] = { 3, 5, 9, 1, 6, 4 };     // two different collections     typedef CountedPtr<int> IntPtr;     deque<IntPtr> coll1;     list<IntPtr> coll2;     /* insert shared objects into the collections      * - same order in coll1      * - reverse order in coll2      */     for (int i=0; i<sizeof(values)/sizeof(values[0]); ++i) {         IntPtr ptr(new int(values[i]));         coll1.push_back(ptr);         coll2.push_front(ptr);     }     // print contents of both collections     for_each (coll1.begin(), coll1.end(),printCountedPtr);     cout << endl;     for_each (coll2.begin(), coll2.end(),printCountedPtr);     cout << endl << endl;     /* modify values at different places      * - square third value in coll1      * - negate first value in coll1      * - set first value in coll2 to 0      */     *coll1[2] *= *coll1[2];     (**coll1.begin()) *= -1;     (**coll2.begin()) = 0;     // print contents of both collections again     for_each (coll1.begin(), coll1.end(),printCountedPtr);     cout << endl;     for_each (coll2.begin(), coll2.end(),printCountedPtr);     cout << endl; } 3 5 9 1 6 4 4 6 1 9 5 3 -3 5 81 1 6 0 0 6 1 81 5 -3