Smart Pointers in C++

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).

This page constructed by Cliff Green, Copyright © 2001.