// (C) Porkolab 2003 // // A.5.7. // // auto_ptr #include <iostream> #include <memory> using namespace std; /* define output operator for auto_ptr * - print object value or NULL */ template <class T> ostream& operator<< (ostream& os, const auto_ptr<T>& p) { // does p own an object ? if (p.get() == NULL) { os << "NULL"; // NO: print NULL } else { os << *p; // YES: print the object } return os; } int main() { auto_ptr<int> p(new int(42)); auto_ptr<int> q; cout << "after initialization:" << endl; cout << " p: " << p << endl; cout << " q: " << q << endl; q = p; cout << "after assigning auto pointers:" << endl; cout << " p: " << p << endl; cout << " q: " << q << endl; *q += 13; // change value of the object q owns p = q; cout << "after change and reassignment:" << endl; cout << " p: " << p << endl; cout << " q: " << q << endl; } /* after initialization: p: 42 q: NULL after assigning auto pointers: p: NULL q: 42 after change and reassignment: p: 55 q: NULL */ namespace std { // auxiliary type to enable copies and assignments (now global) template<class Y> struct auto_ptr_ref { Y* yp; auto_ptr_ref (Y* rhs) : yp(rhs) { } }; template<class T> class auto_ptr { private: T* ap; // refers to the actual owned object (if any) public: typedef T element_type; // constructor explicit auto_ptr (T* ptr = 0) throw() : ap(ptr) { } // copy constructors (with implicit conversion) // - note: nonconstant parameter auto_ptr (auto_ptr& rhs) throw() : ap(rhs.release()) { } template<class Y> auto_ptr (auto_ptr<Y>& rhs) throw() : ap(rhs.release()) { } // assignments (with implicit conversion) // - note: nonconstant parameter auto_ptr& operator= (auto_ptr& rhs) throw() { reset(rhs.release()); return *this; } template<class Y> auto_ptr& operator= (auto_ptr<Y>& rhs) throw() { reset(rhs.release()); return *this; } // destructor ~auto_ptr() throw() { delete ap; } // value access T* get() const throw() { return ap; } T& operator*() const throw() { return *ap; } T* operator->() const throw() { return ap; } // release ownership T* release() throw() { T* tmp(ap); ap = 0; return tmp; } // reset value void reset (T* ptr=0) throw() { if (ap != ptr) { delete ap; ap = ptr; } } // special conversions with auxiliary type // to enable copies and assignments auto_ptr(auto_ptr_ref<T> rhs) throw() : ap(rhs.yp) { } auto_ptr& operator= (auto_ptr_ref<T> rhs) throw() { reset(rhs.yp); return *this; } template<class Y> operator auto_ptr_ref<Y>() throw() { return auto_ptr_ref<Y>(release()); } template<class Y> operator auto_ptr<Y>() throw() { return auto_ptr<Y>(release()); } }; }