正確使用auto_ptr智慧指標

zyex1108發表於2016-12-29

1, auto_ptr類

auto_ptr是一個模板類,定義如下:

template <typenameType>
class auto_ptr {...};
它儲存的是一個指向Type的指標。

顧名思義,auto_ptr是一種智慧指標,它包含一個動態分配記憶體的指標,並在它生命週期結束的時候,銷燬包含的指標所指向的記憶體。

 例1:

void f()
    {
        Type* pt(new Type);
        //一些程式碼...
        delete pt;
    }
這樣的程式碼很常見,但它有可能造成記憶體洩露。首先你用了new,你就要記得用delete,但即使你記住了用delete,還是會出問題。如果f()在執行delete pt之前,就丟擲了異常,函式返回了。那麼這個分配的物件就沒被刪除。

 使用auto_ptr,很優雅的解決了這些問題。

例2:

void f()
        {
              auto_ptr<Type> pt(new Type);
              //一些程式碼...
        }
現在的程式碼,不會洩露Type型別的物件。不管是函式正常結束,還是丟擲異常結束,都會呼叫pt的解構函式,從而刪除分配的物件。

 2, auto_ptr建構函式

建構函式1:

explicitauto_ptr(Type*_Ptr= 0) throw( );
            auto_ptr<int> pt; //包含一個int*的指標,並初始化為NULL
            auto_ptr<int> pt(new int(123));//包含一個int*的指標,並初始化為123的地址
            auto_ptr<int> pt =new int(123);//error!建構函式宣告為explicit
 建構函式2:

auto_ptr(auto_ptr<Type>&_Right)throw( );
             int* ptr =new int();
            auto_ptr<int> pt1(ptr); //建構函式1
            auto_ptr<int> pt2(pt1);//將pt1的使用權轉給pt2,注意pt1指向NULL了  //pt1呼叫了本身的release()函式,將內部指標地址傳給pt2
 建構函式3:

template<typename Other>       
             auto_ptr(auto_ptr<Other>&_Right)throw( );//宣告這樣一個拷貝建構函式的目的,就是為了派生類指標能轉換成基類的指標。
 例:
      class Base { };
      class Derived :public Base { };
      auto_ptr<Derived> pDerived(new Derived);
      auto_ptr<Base>    pBase(pDerived);    //讓這樣的程式碼能通過編譯器
      其本質是為了讓,auto_ptr類內部的Derived*轉換為Base*
建構函式4:

auto_ptr(auto_ptr_ref<Type>_Right)throw( );

                        //暫略
3, auto_ptr成員函式

成員函式1:

Type* get( )const throw( );
                獲得包含指標的地址
                int* ptr = new int(123);
                auto_ptr<int> pt(ptr);
                assert(pt.get() == ptr); //相等,指向同一地址
成員函式2:

Type* release( )throw( );
                   返回包含指標的地址,並將包含指標設為NUll
                   string* pstr = new string("hello");
                   auto_ptr<string> pt(pstr);
                   pt.release();   //不在指向string物件                                       //此時,pt.get()等於NULL
                   delete pstr;    //應該手動刪除pstr指向的記憶體塊 
成員函式3:

void reset(Type* _Ptr = 0);
    double* pdouble1 = new double(3.14);
    double* pdouble2 = new double(1.23);
    auto_ptr<double> pt1(pdouble1);
    pt1.reset(pdouble2);  //將刪除pt1所指向的記憶體塊就是pdouble1指向的那塊 //此時,pt.get()等於pdouble2
    cout << *pdouble1;   //error,pdouble已經是野指標了。
4, 使用總結

1,auto_ptr儲存的指標應該為NULL或者指向動態分配的記憶體塊。

2,auto_ptr儲存的指標應該指向單一物件(是new出來的,而不是new[]出來的)。

3,兩個auto_ptr物件不會同時指向同一塊記憶體塊。要明白2個auto_ptr物件賦值會發生什麼。

4,千萬不要把auto_ptr物件放在容器中。

5,當將auto_ptr作為函式引數時,最好宣告為const auto_ptr<T>&(by const ref).當函式返回值可以簡單的傳值(by value).

相關文章