C++ Tutorial/Pointer/auto ptr

Материал из C\C++ эксперт
Версия от 10:30, 25 мая 2010; Admin (обсуждение | вклад) (1 версия: Импорт контента...)
(разн.) ← Предыдущая | Текущая версия (разн.) | Следующая → (разн.)
Перейти к: навигация, поиск

class auto_ptr: improved standard conforming implementation

/* The following code example is taken from the book
 * "The C++ Standard Library - A Tutorial and Reference"
 * by Nicolai M. Josuttis, Addison-Wesley, 1999
 *
 * (C) Copyright Nicolai M. Josuttis 1999.
 * Permission to copy, use, modify, sell and distribute this software
 * is granted provided this copyright notice appears in all copies.
 * This software is provided "as is" without express or implied
 * warranty, and with no claim as to its suitability for any purpose.
 */
/* class auto_ptr
 * - improved standard conforming implementation
 */
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() {  // new
             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());
        }
    };
}

const auto_ptr

/* The following code example is taken from the book
 * "The C++ Standard Library - A Tutorial and Reference"
 * by Nicolai M. Josuttis, Addison-Wesley, 1999
 *
 * (C) Copyright Nicolai M. Josuttis 1999.
 * Permission to copy, use, modify, sell and distribute this software
 * is granted provided this copyright notice appears in all copies.
 * This software is provided "as is" without express or implied
 * warranty, and with no claim as to its suitability for any purpose.
 */
#include <iostream>
#include <memory>
using namespace std;
/* define output operator for auto_ptr
 * - print object value or NULL
 */
template <class T>
ostream& operator<< (ostream& strm, const auto_ptr<T>& p)
{
    // does p own an object ?
    if (p.get() == NULL) {
        strm << "NULL";         // NO: print NULL
    }
    else {
        strm << *p;             // YES: print the object
    }
    return strm;
}
int main()
{
    const auto_ptr<int> p(new int(42));
    const auto_ptr<int> q(new int(0));
    const auto_ptr<int> r;
    cout << "after initialization:" << endl;
    cout << " p: " << p << endl;
    cout << " q: " << q << endl;
    cout << " r: " << r << endl;
    *q = *p;
//  *r = *p;    // ERROR: undefined behavior
    *p = -77;
    cout << "after assigning values:" << endl;
    cout << " p: " << p << endl;
    cout << " q: " << q << endl;
    cout << " r: " << r << endl;
//  q = p;      // ERROR at compile time
//  r = p;      // ERROR at compile time
}
after initialization:
 p: 42
 q: 0
 r: NULL
after assigning values:
 p: -77
 q: 42
 r: NULL

Define output operator for auto_ptr print object value or NULL

/* The following code example is taken from the book
 * "The C++ Standard Library - A Tutorial and Reference"
 * by Nicolai M. Josuttis, Addison-Wesley, 1999
 *
 * (C) Copyright Nicolai M. Josuttis 1999.
 * Permission to copy, use, modify, sell and distribute this software
 * is granted provided this copyright notice appears in all copies.
 * This software is provided "as is" without express or implied
 * warranty, and with no claim as to its suitability for any purpose.
 */
#include <iostream>
#include <memory>
using namespace std;
/* define output operator for auto_ptr
 * - print object value or NULL
 */
template <class T>
ostream& operator<< (ostream& strm, const auto_ptr<T>& p)
{
    // does p own an object ?
    if (p.get() == NULL) {
        strm << "NULL";         // NO: print NULL
    }
    else {
        strm << *p;             // YES: print the object
    }
    return strm;
}
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

Demonstrate an auto_ptr

#include <iostream>
#include <memory>
using namespace std;
class MyClass {
public:
  MyClass() {
     cout << "constructing\n";
  }
  ~MyClass() {
     cout << "destructing\n";
  }
  void f() {
     cout << "f()\n";
  }
};
int main()
{
  auto_ptr<MyClass> p1(new MyClass), p2;
  p2 = p1; // transfer ownership
  p2->f();
  // can assign to a normal pointer
  MyClass *ptr = p2.get();
  ptr->f();
  return 0;
}
constructing
f()
f()
destructing