FAQ 31.09 How easy is it to implement reference counting with pointer semantics?

graphics/new_icon.gif

It is relatively easy, and the result is worthwhile.

If the application tends to pass around pointers to dynamically allocated objects and possibly store some of the pointers in containers, it is quite possible that there will be either memory leaks or dangling references. Often a simple reference-counting scheme suffices in these circumstances.

Reference counting means that each object keeps track of how many pointers are pointing at it, and when the object no longer has any pointers pointing at it, the object deletes itself. With a little discipline, this means that the object dies when it becomes unreachable, which is precisely what is desired. A very simple implementation of this technique follows.

 class FredPtr; class Fred { public:   Fred() throw()      : count_(0) /*...*/ { }  // All ctors set count_ to 0 !   // ... private:   friend FredPtr;     // A friend class   unsigned count_;   // count_ must be initialized to 0 by all constructors   // count_ is the number of FredPtr objects that point at   // the this object }; class FredPtr { public:   FredPtr(Fred* p) throw()     : p_(p) { if (p_) ++p_->count_; }  ~FredPtr() throw()     { if (p_ && --p_->count_ == 0) delete p_; }   FredPtr(const FredPtr& p) throw()     : p_(p.p_) { if (p_) ++p_->count_; }   FredPtr& operator= (const FredPtr& p) throw();   Fred* operator-> () throw() { return p_;  }   Fred& operator* () throw()  { return *p_; }   Fred* getRaw() throw()      { return p_;  } private:   Fred* p_; }; FredPtr& FredPtr::operator= (const FredPtr& p) throw() {   // DO NOT CHANGE THE ORDER OF THESE STATEMENTS!   // (This order properly handles self-assignment; see FAQ 24.02)   if (p.p_) ++p.p_->count_;   if (p_ && --p_->count_ == 0) delete p_;   p_ = p.p_;   return *this; } 

This simple reference-counting mechanism provides users with a pointer-oriented view of the Fred objects. In other words, users always allocate their Fred objects via new and point to the Fred objects via FredPtr "smart pointers." Users can make as many copies of their FredPtr pointers as they wish, including storing some FredPtrs in containers, and the pointed-to Fred objects are automatically deleted when the last such FredPtr object vanishes.

To hide the pointers from users so that users see objects rather than pointers to objects, use reference counting with copy-on-write semantics (see FAQ 31.10).

Note that the constraint that all Fred objects be allocated via new can be enforced using the named constructor idiom (see FAQ 16.08). In this case, it means making all Fred constructors private: and defining each named constructor as a public: static create() member function. The public: static create() member function would allocate a new Fred object and would return the resulting pointer as a FredPtr (not a Fred*). Users would then use FredPtr p = Fred::create() rather than FredPtr p = new Fred().



C++ FAQs
C Programming FAQs: Frequently Asked Questions
ISBN: 0201845199
EAN: 2147483647
Year: 2005
Pages: 566
Authors: Steve Summit

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net