reference counting
1 #include < string > 2 #include < iostream > 3 using namespace std; 4 5 class Dog 6 { 7 string nm; 8 int refcount; 9 Dog( const string & name) : nm(name), refcount( 1 ) 10 { 11 cout << " Creating Dog: " << * this << endl; 12 } 13 14 Dog & operator = ( const Dog & rv); 15 public : 16 static Dog * make( const string & name) 17 { 18 return new Dog(name); 19 } 20 21 Dog( const Dog & d) : nm(d.nm + " copy " ), refcount( 1 ) 22 { 23 cout << " Dog copy-constructor: " << * this << endl; 24 } 25 26 ~ Dog() 27 { 28 cout << " Deleting Dog: " << * this << endl; 29 } 30 31 void attach() 32 { 33 ++ refcount; 34 cout << " Attached Dog: " << * this << endl; 35 } 36 37 void detach() 38 { 39 cout << " Detaching Dog: " << * this << endl; 40 if ( -- refcount == 0 ) 41 { 42 delete this ; 43 } 44 } 45 46 Dog * unalias() 47 { 48 cout << " Unaliasing Dog: " << * this << endl; 49 if (refcount == 1 ) 50 { 51 return this ; 52 } 53 -- refcount; 54 return new Dog( * this ); 55 } 56 57 void rename( const string & newName) 58 { 59 nm = newName; 60 cout << " Dog renamed to " << * this << endl; 61 } 62 63 friend ostream & operator << (ostream & os, const Dog & d) 64 { 65 return os << " [ " << d.nm << " ], rc = " << d.refcount; 66 } 67 }; 68 69 70 class DogHouse 71 { 72 Dog * p; 73 string houseName; 74 public : 75 DogHouse(Dog * dog, const string & house) : p(dog), houseName(house) 76 { 77 cout << " Creating DogHouse: " << * this << endl; 78 } 79 80 DogHouse( const DogHouse & dh) : p(dh.p), houseName( " copy-constructed " + dh.houseName) 81 { 82 p -> attach(); 83 cout << " DogHouse copy-constructed: " << * this << endl; 84 } 85 86 DogHouse & operator = ( const DogHouse & dh) 87 { 88 if ( & dh != this ) 89 { 90 houseName = dh.houseName + " assigned " ; 91 p -> detach(); 92 p = dh.p; 93 p -> attach(); 94 } 95 96 cout << " DogHouse operator= : " << * this << endl; 97 return * this ; 98 } 99 100 ~ DogHouse() 101 { 102 cout << " DogHouse destructor: " << * this << endl; 103 p -> detach(); 104 } 105 106 void renameHouse( const string & newName) 107 { 108 houseName = newName; 109 } 110 111 void unalias() 112 { 113 p = p -> unalias(); 114 } 115 116 void renameDog( const string & newName) 117 { 118 unalias(); 119 p -> rename(newName); 120 } 121 122 Dog * getDog() 123 { 124 unalias(); 125 return p; 126 } 127 128 friend ostream & operator << (ostream & os, const DogHouse & dh) 129 { 130 return os << " [ " << dh.houseName << " ] contains " << * dh.p; 131 } 132 133 }; 134 135 int main() 136 { 137 DogHouse fidos(Dog::make( " Fido " ), " FidoHouse " ), spots(Dog::make( " Spot " ), " SpotHouse " ); 138 cout << " Entering copy-construction " << endl; 139 DogHouse bobs(fidos); 140 cout << " After copy-constructing bobs " << endl; 141 cout << " fidos: " << fidos << endl; 142 cout << " spots: " << spots << endl; 143 cout << " bobs: " << bobs << endl; 144 cout << " Entering spots = fidos " << endl; 145 spots = fidos; 146 cout << " After spots = fidos " << endl; 147 cout << " spots: " << spots << endl; 148 cout << " Entering self-assignment " << endl; 149 bobs = bobs; 150 cout << " After self-assignment " << endl; 151 cout << " bobs: " << bobs << endl; 152 // Comment out the following lines: 153 cout << " Entering rename(\ " Bob\ " ) " << endl; 154 bobs.getDog() -> rename( " Bob " ); 155 cout << " After rename(\ " Bob\ " ) " << endl; 156 }