Reference counting pointer.
Class GP<TYPE> represents a smart-pointer to an object of type TYPE.
Type TYPE must be a subclass of GPEnabled. This class overloads the
usual pointer assignment and dereferencing operators. The overloaded
operators maintain the reference counters and destroy the pointed object
as soon as their reference counter reaches zero. Transparent type
conversions are provided between smart-pointers and regular pointers.Using a smart-pointer is a convenience and not an obligation. There is no
need to use a smart-pointer to access a GPEnabled object. As long as
you never use a smart-pointer to access a GPEnabled object, its
reference counter remains zero. Since the reference counter is never
decremented from one to zero, the object is never destroyed by the
reference counting code. You can therefore choose to only use regular
pointers to access objects allocated on the stack (automatic variables) or
objects allocated dynamically. In the latter case you must explicitly
destroy the dynamically allocated object with operator delete.
The first time you use a smart-pointer to access GPEnabled object, the
reference counter is incremented to one. Object destruction will then
happen automatically when the reference counter is decremented back to
zero (i.e. when the last smart-pointer referencing this object stops doing so).
This will happen regardless of how many regular pointers reference this object.
In other words, if you start using smart-pointers with a GPEnabled
object, you engage automatic mode for this object. You should only do
this with objects dynamically allocated with operator new. You should
never destroy the object yourself, but let the smart-pointers control the
life of the object.
Performance considerations --- Thread safe reference counting incurs
a significant overhead. Smart-pointer are best used with sizeable objects
for which the cost of maintaining the counters represent a small fraction
of the processing time. It is always possible to cache a smart-pointer
into a regular pointer. The cached pointer will remain valid until the
smart-pointer object is destroyed or the smart-pointer value is changed.
Safety considerations --- As explained above, a GPEnabled object
switches to automatic mode as soon as it becomes referenced by a
smart-pointer. There is no way to switch the object back to manual mode.
Suppose that you have decided to only use regular pointers with a
particular GPEnabled object. You therefore plan to destroy the object
explicitly when you no longer need it. When you pass a regular pointer to
this object as argument to a function, you really need to be certain that
the function implementation will not assign this pointer to a
smart-pointer. Doing so would indeed destroy the object as soon as the
function returns. The bad news is that the fact that a function assigns a
pointer argument to a smart-pointer does not necessarily appear in the
function prototype. Such a behavior must be documented with the
function public interface. As a convention, we usually write such
functions with smart-pointer arguments instead of a regular pointer
arguments. This is not enough to catch the error at compile time, but
this is a simple way to document such a behavior. We still believe that
this is a small problem in regard to the benefits of the smart-pointer.
But one has to be aware of its existence.