The C++ Standard Library之auto_ptr

auto_ptr, 可以联想 c的alloca()。alloca和auto_ptr只有自动释放的共性。
    p40
   a.    auto_ptr 是這樣一種指標:它是「它所指向的物件」的擁有者(owner)。
             auto_ptr 要求,一 個物件只能有一個擁有者,嚴禁一物二主。

   b.    auto_ptr是区域变数,无论是正常退出,还是异常退出,只要函式退出,就一定会被销毁。
           无论何种情况下,auto_ptr被销毁,就一定连带释放其所指资源。

   c.     絕對不應 該出現多個auto_ptrs 同時擁有一個物件的情況。不幸的是,這種事情可能會發
          (如果你以同一個物件為初值,將兩個 auto_ptr s 初始化,就會出現這種事)。 程式員必須負責防範這種錯誤。

   d.     auto_ptr 的copy 建構式和 assignment運算子將物件擁有權交出去。
           有者一旦交出擁有 權,就兩手空空,只剩一個null指標在手了。     //注意

   e.    使用auto_ptr,要清楚是否需要交接拥有权和拥有权交接点。

   f.    auto_ptr 的語義本身就涵蓋擁有權,所以如果你無意轉交你的擁有權,就不要在 參數列中使用auto_ptr ,也不要以它作爲回返值。
         //bad example         
           std::auto_ptr<int> p(new int);
         *p = 42;                      // change value to which p refers
         bad_print(p);               // Oops, deletes the memory to which p refers
        *p = 18;                      // RUNTIME ERROR
        
         const  std::auto_ptr<int> p(new int);     //p44
         總而言之,常數型auto_ptr 減小了「不經意轉移擁有權」所帶來的危險。只要一 個物件藉由auto_ptr 傳遞,就可以使用常數型auto_ptr
           來終結擁有權移轉鏈, 此後擁有權將不能再進行移轉。
        關鍵字const 並非意味你不能更改auto_ptr 所擁有的物件,而是意味 你不能更改auto_ptr 的擁有權。

  g.     將auto_ptr s 以pass by reference 方式傳遞就萬事大吉。然而這 種行爲卻會使「擁有權」的概念變得難以捉摸,因爲面對一個「透過reference 而
         獲得auto_ptr 」的函式,你根本無法預知擁有權是否被轉交。所以以 by reference 方式傳遞auto_ptr 是非常糟糕的設計,應該全力避免。

         p46    auto_ptr的4个错误运用,详见原文。

autoptr.hpp
/* 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) {
         	cout << "explicit auto_ptr() excute..." << endl;
		 	if(ptr)
		 	{
				cout << "explicit auto_ptr() *ap:" << *ptr << endl;
			}
        }

        // copy constructors (with implicit conversion)
        // - note: nonconstant parameter
        auto_ptr (auto_ptr& rhs) throw()
         : ap(rhs.release()) {
         cout << "auto_ptr (auto_ptr& rhs) excute..." << endl;
        }
        template<class Y>
        auto_ptr (auto_ptr<Y>& rhs) throw()
         : ap(rhs.release()) {
		cout << "auto_ptr (auto_ptr<Y>& rhs) excute..." << endl;
        }
        
        // assignments (with implicit conversion)
        // - note: nonconstant parameter
        auto_ptr& operator= (auto_ptr& rhs) throw() {
			cout << "operator= (auto_ptr& rhs) excute..." << endl;
            reset(rhs.release());
            return *this;
        }
        template<class Y>
        auto_ptr& operator= (auto_ptr<Y>& rhs) throw() {
			cout << "operator= (auto_ptr<Y>& rhs) excute..." << endl;
            reset(rhs.release());
            return *this;
        }
        
        // destructor
        ~auto_ptr() throw() {
            delete ap;
        }

        // value access
        T* get() const throw() {
            return ap;
        }
        T& operator*() const throw() {
			cout << "operator*() excute..." << endl;
			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) {
		 cout << "auto_ptr(auto_ptr_ref<T> rhs) excute..." << endl;
        }
        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());
        }
    };
}

main.cpp
/* 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>
#include "autoptr.hpp"

using namespace std;

/* define output operator for auto_ptr
 * - print object value or NULL
 */
#if 0	
//test 1,允许转移,且有转移
ostream& operator<< (ostream& strm, auto_ptr<T>& p)
{
	......
	auto_ptr<T> tmp = p;	
}

//test 2,不允许转移,但有转移
ostream& operator<< (ostream& strm,  const auto_ptr<T>& p)
{
	......
	auto_ptr<T> tmp = p;
}

#endif

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
    }

	//auto_ptr<T> tmp = p;	
	return strm;
}

int main()
{
    auto_ptr<int> r(new int(43));
    auto_ptr<int> s = r;		//copy constructor
	cout << "##############" << endl << endl;
	
    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;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值