This page last updated on:
May 16, 2001
Contents and Related Links
CodeWrangler Pages
|
Smart pointers give extra control over regular pointers by managing
construction and destruction (initialized to zero, automatically destroy
the heap object when done), copy and assignment (what happens when the
pointer is copied or assigned to?), and dereferencing (lazy evaluation
could be implemented). Reference counting is a common technique used to
manage multiple objects sharing the same resource (such as a heap object).
The Boost library boost::shared_ptr class (http://www.boost.org/)
is a high quality implementation of reference counting on heap objects.
Smart pointers provide a high-level 'pointer abstraction' while managing
the heap object.
Smart pointers (and the std::auto_ptr class) are extremely
useful in writing exception safe code, since a smart pointer object is
created as a local object (on the stack). When a smart pointer is destructed
by going out of scope (either because of a thrown exception or from a return
from a function or local block), the heap object gets handled correctly.
True smart pointers can also be used in std library containers (std::auto_ptr
cannot be used in containers).
A smart pointer implementation typically has the following characteristics
(summarized from a C++ Report article, Nov/Dec 1998):
-
A smart pointer has a built-in pointer as a data member, which refers to
the heap object. The constructor argument is the heap object pointer, typically
a templatized type.
-
The dereferencing operators operator->() and operator*()
are defined and implemented by forwarding their operations to the built-in
pointer (provides similar syntax for regulars pointers as for the smart
pointer).
-
A smart pointer usually provides reference counting (note that the std::auto_ptr
class is not a true smart pointer class).
Pointer management is commonly needed and generally useful enough that
the std::auto_ptr class is part of the C++ standard. It encapsulates
pointer handling eliminating the need to explicitly delete a new'ed
object, as well as providing safe copy construction and assignment semantics.
The std::auto_ptr class is templatized providing type-safe operations
(particularly delete). The std::auto_ptr class gives
a good illustration of explicit constructors and member function templates.
Object ownership is maintained and transferred upon copying or assignment.
The std::auto_ptr class is more limited than most smart pointer
classes, although more efficient. Typical implementations of the std::auto_ptr
contain only the internal heap pointer, saving the memory and access overheads
of a smart pointer. However, the std::auto_ptr class uses the
concept of 'strict ownership', leading to significantly different semantics
for std::auto_ptr compared to a smart pointer. A summary of strict
ownership is:
-
One and only one std::auto_ptr object owns the referred object
on the heap.
-
Copy construction and assignment pass the ownership from one std::auto_ptr
object to the other.
-
When a std::auto_ptr object is destroyed it not only gives up
the ownership, but also destroys the owned object.
Correct and intended usages of std::auto_ptr objects include locally
scoped heap objects that are exception-safe, input function arguments,
and output function arguments, and class member data, as long as copy construction
and assignment operator are overloaded and properly handled (letting the
compiler generate these will not work). Incorrect usages include using
std::auto_ptr
for non-heap pointers, constructing two std::auto_ptr objects
from the same heap object pointer, using a std::auto_ptr object
as member data AND not handling copy construction and assignment correctly
for the enclosing class, and more importantly using std::auto_ptr
objects inside a container object (notably any of the standard library
containers). The important concept to knowing the strengths and weaknesses
of the std::auto_ptr class is to realize that it is not 'copy
constructible'. Copy constructible means that an object and a copy of that
object are equivalent. The copy constructor for std::auto_ptr has
a non-const reference for the right-hand-side to provide for const-correctness.
However, there are times a copy is needed of std::auto_ptr 'rvalues',
and a special nested class named auto_ptr_ref is present in the
std::auto_ptr
class which converts and creates copies as needed in correct situations.
There are two member functions of the std::auto_ptr class that
are sometimes needed to get access to the internal pointer:
-
get() - provides a copy of the internal pointer (but does not
transfer ownership).
-
release() - provides a copy of the internal pointer, and transfers
ownership (nulls out the internal pointer, so that when the std::auto_ptr
is destructed, nothing happens).
|