template <class T>
class Handle {
public:
// unbound handle
Handle(T *p = 0): ptr(p), use(new size_t(1)) { }
// overloaded operators to support pointer behavior
T& operator*();
T* operator->();
const T& operator*() const;
const T* operator->() const;
// copy control: normal pointer behavior, but last Handle deletes the object
Handle(const Handle& h): ptr(h.ptr), use(h.use)
{ ++*use; }
Handle& operator=(const Handle&);
~Handle() { rem_ref(); }
private:
T* ptr; // shared object
size_t *use; // count of how many Handles point to *ptr
void rem_ref()
{ if (--*use == 0) { delete ptr; delete use; } }
};
template <class T>
inline Handle<T>& Handle<T>::operator=(const Handle &rhs)
{
++*rhs.use; // protect against self-assignment
rem_ref(); // decrement use count and delete pointers if needed
ptr = rhs.ptr;
use = rhs.use;
return *this;
}
template <class T> inline T& Handle<T>::operator*()
{
if (ptr) return *ptr;
throw std::runtime_error
("dereference of unbound Handle");
}
template <class T> inline T* Handle<T>::operator->()
{
if (ptr) return ptr;
throw std::runtime_error
("access through unbound Handle");
}
template <class T> inline
const T& Handle<T>::operator*() const
{
if (ptr) return *ptr;
throw std::runtime_error("dereference of unbound Handle");
}
template <class T> inline
const T* Handle<T>::operator->() const
{
if (ptr) return ptr;
throw std::runtime_error("access through unbound Handle");
}
int main()
{
{ // new scope
// user allocates but must not delete the object to which the Handle is attached
Handle<int> hp(new int(42));
{ // new scope
Handle<int> hp2 = hp; // copies pointer; use count incremented
cout << *hp << " " << *hp2 << endl; // prints 42 42
*hp2 = 10; // changes value of shared underlying int
} // hp2 goes out of scope; use count is decremented
cout << *hp << endl; // prints 10
} // hp goes out of scope; its destructor deletes the int
}