Items 9, 10, 26, 31 and 32 attest to the remarkable utility of the auto_ptr
template. Unfortunately, few compilers currently ship with a "correct" implementation.1 Items 9 and 28 sketch how you might write one yourself, but it's nice to have more than a sketch when embarking on real-world
Below are two presentations of an implementation for auto_ptr
. The first presentation documents the class interface and implements all the member functions outside the class definition. The second implements each member function within the class definition. Stylistically, the second presentation is inferior to the first, because it fails to separate the class interface from its implementation. However, auto_ptr
yields simple classes, and the second presentation brings that out much more clearly than does the
Here is auto_ptr
with its interface
template<class T> class auto_ptr { public: explicit auto_ptr(T *p = 0); // see Item 5 for a // description of "explicit"
template<class U> // copy constructor member auto_ptr(auto_ptr<U>& rhs); // template (see Item 28): // initialize a new auto_ptr // with any compatible // auto_ptr
~auto_ptr();
template<class U> // assignment operator auto_ptr<T>& // member template (see operator=(auto_ptr<U>& rhs); // Item 28): assign from any // compatible auto_ptr
T& operator*() const; // see Item 28 T* operator->() const; // see Item 28
T* get() const; // return value of current // dumb pointer
T* release(); // relinquish ownership of // current dumb pointer and // return its value
void reset(T *p = 0); // delete owned pointer; // assume ownership of p private: T *pointee;
template<class U> // make all auto_ptr classes friend class auto_ptr<U>; // friends of one another };
template<class T> inline auto_ptr<T>::auto_ptr(T *p) : pointee(p) {}
template<class T> inline auto_ptr<T>::auto_ptr(auto_ptr<U>& rhs) : pointee(rhs.release()) {}
template<class T> inline auto_ptr<T>::~auto_ptr() { delete pointee; }
template<class T> template<class U> inline auto_ptr<T>& auto_ptr<T>::operator=(auto_ptr<U>& rhs) { if (this != &rhs) reset(rhs.release()); return *this; }
template<class T> inline T& auto_ptr<T>::operator*() const { return *pointee; }
template<class T> inline T* auto_ptr<T>::operator->() const { return pointee; }
template<class T> inline T* auto_ptr<T>::get() const { return pointee; }
template<class T> inline T* auto_ptr<T>::release() { T *oldPointee = pointee; pointee = 0; return oldPointee; }
template<class T> inline void auto_ptr<T>::reset(T *p) { if (pointee != p) { delete pointee; pointee = p; } }
Here is auto_ptr
with all the functions defined in the class definition. As you can see, there's no brain surgery going on
template<class T> class auto_ptr { public: explicit auto_ptr(T *p = 0): pointee(p) {}
template<class U> auto_ptr(auto_ptr<U>& rhs): pointee(rhs.release()) {}
~auto_ptr() { delete pointee; }
template<class U> auto_ptr<T>& operator=(auto_ptr<U>& rhs) { if (this != &rhs) reset(rhs.release()); return *this; }
T& operator*() const { return *pointee; }
T* operator->() const { return pointee; }
T* get() const { return pointee; }
T* release() { T *oldPointee = pointee; pointee = 0; return oldPointee; }
void reset(T *p = 0) { if (pointee != p) { delete pointee; pointee = p; } } private: T *pointee; template<class U> friend class auto_ptr<U>; };
If your compilers don't yet support explicit
, you may safely #define
it out of
#define explicit
This won't make auto_ptr
any less functional, but it will render it slightly less safe. For details, see Item 5.
If your compilers lack support for member templates, you can use the non-template auto_ptr
copy constructor and assignment operator described in Item 28. This will make your auto_ptr
s less convenient to use, but there is, alas, no way to approximate the behavior of member templates. If member templates (or other language features, for that matter) are important to you, let your compiler vendors know. The more customers ask for new language features, the sooner vendors will implement
auto_ptr
as for years been a moving target. The final specification was adopted only in
November 1997. For details, consult auto_ptr
information at this book's WWW Site.
Note that the auto_ptr
described here omits a few details present in the official version, such as the fact that auto_ptr
is in the std
namespace (see Item 35) and that its member functions promise not to throw exceptions.