<menu id="w8yyk"><menu id="w8yyk"></menu></menu>
  • <dd id="w8yyk"><nav id="w8yyk"></nav></dd>
    <menu id="w8yyk"></menu>
    <menu id="w8yyk"><code id="w8yyk"></code></menu>
    <menu id="w8yyk"></menu>
    <xmp id="w8yyk">
    <xmp id="w8yyk"><nav id="w8yyk"></nav>
  • 網站首頁 > 物聯資訊 > 技術分享

    C++智能指針(auto_ptr)詳解

    2016-09-28 00:00:00 廣州睿豐德信息科技有限公司 閱讀
    睿豐德科技 專注RFID識別技術和條碼識別技術與管理軟件的集成項目。質量追溯系統、MES系統、金蝶與條碼系統對接、用友與條碼系統對接

    智能指針(auto_ptr) 這個名字聽起來很酷是不是?其實auto_ptr 只是C++標準庫提供的一個類模板,它與傳統的new/delete控制內存相比有一定優勢,但也有其局限。本文總結的8個問題足以涵蓋auto_ptr的大部分內容。

     

    1. auto_ptr是什么?

    auto_ptr 是C++標準庫提供的類模板,auto_ptr對象通過初始化指向由new創建的動態內存,它是這塊內存的擁有者,一塊內存不能同時被分給兩個擁有者。當auto_ptr對象生命周期結束時,其析構函數會將auto_ptr對象擁有的動態內存自動釋放。即使發生異常,通過異常的棧展開過程也能將動態內存釋放。auto_ptr不支持new 數組。

     

    2. auto_ptr需要包含的頭文件?

    #include <memory>

     

    3. 初始化auto_ptr對象的方法?

    1) 構造函數

    1] 將已存在的指向動態內存的普通指針作為參數來構造

    int* p = new int(33);

    auto_ptr<int> api(p);

    2] 直接構造智能指針

    auto_ptr< int > api( new int( 33 ) );

    2) 拷貝構造

    利用已經存在的智能指針來構造新的智能指針

    auto_ptr< string > pstr_auto( new string( "Brontosaurus" ) );

    auto_ptr< string > pstr_auto2( pstr_auto );  //利用pstr_auto來構造pstr_auto2

    因為一塊動態內存智能由一個智能指針獨享,所以在拷貝構造或賦值時都會發生擁有權轉移的過程。在此拷貝構造過程中,pstr_auto將失去對字符串內存的所有權,而pstr_auto2將其獲得。對象銷毀時,pstr_auto2負責內存的自動銷毀。

    3) 賦值

    利用已經存在的智能指針來構造新的智能指針

    auto_ptr< int > p1( new int( 1024 ) );

    auto_ptr< int > p2( new int( 2048 ) );

    p1 = p2;

    在賦值之前,由p1 指向的對象被刪除。賦值之后,p1 擁有int 型對象的所有權。該對象值為2048。 p2 不再被用來指向該對象。

     

    4. 空的auto_ptr 需要初始化嗎?

    通常的指針在定義的時候若不指向任何對象,我們用Null給其賦值。對于智能指針,因為構造函數有默認值0,我們可以直接定義空的auto_ptr如下:

    auto_ptr< int > p_auto_int;  //不指向任何對象

     

    5. 防止兩個auto_ptr對象擁有同一個對象(一塊內存)

    因為auto_ptr的所有權獨有,所以下面的代碼會造成混亂。

    int* p = new int(0);
    auto_ptr<int> ap1(p);
    auto_ptr<int> ap2(p);

    因為ap1與ap2都認為指針p是歸它管的,在析構時都試圖刪除p, 兩次刪除同一個對象的行為在C++標準中是未定義的。所以我們必須防止這樣使用auto_ptr。

     

    6. 警惕智能指針作為參數!

    1) 按值傳遞時,函數調用過程中在函數的作用域中會產生一個局部對象來接收傳入的auto_ptr(拷貝構造),這樣,傳入的實參auto_ptr就失去了其對原對象的所有權,而該對象會在函數退出時被局部auto_ptr刪除。如下例:

    void f(auto_ptr<int> ap)

    {cout<<*ap;}
    auto_ptr<int> ap1(new int(0));
    f(ap1);
    cout<<*ap1; //錯誤,經過f(ap1)函數調用,ap1已經不再擁有任何對象了。

    2) 引用或指針時,不會存在上面的拷貝過程。但我們并不知道在函數中對傳入的auto_ptr做了什么,如果當中某些操作使其失去了對對象的所有權,那么這還是可能會導致致命的執行期錯誤。

    結論:const reference是智能指針作為參數傳遞的底線。

     

    7. auto_ptr不能初始化為指向非動態內存

    原因很簡單,delete 表達式會被應用在不是動態分配的指針上這將導致未定義的程序行為。

     

    8. auto_ptr常用的成員函數

    1) get()

    返回auto_ptr指向的那個對象的內存地址。如下例:

    int* p = new int(33);

    cout << "the adress of p: "<< p << endl;

    auto_ptr<int> ap1(p);

    cout << "the adress of ap1: " << &ap1 << endl;

    cout << "the adress of the object which ap1 point to: " << ap1.get() << endl;

    輸出如下:

    the adress of p: 00481E00

    the adress of ap1: 0012FF68

    the adress of the object which ap1 point to: 00481E00

    第一行與第三行相同,都是int所在的那塊內存的地址。第二行是ap1這個類對象本身所在內存的地址。

    2) reset()

    重新設置auto_ptr指向的對象。類似于賦值操作,但賦值操作不允許將一個普通指針指直接賦給auto_ptr,而reset()允許。如下例:

    auto_ptr< string > pstr_auto( new string( "Brontosaurus" ) );

    pstr_auto.reset( new string( "Long -neck" ) );

    在例子中,重置前pstr_auto擁有"Brontosaurus"字符內存的所有權,這塊內存首先會被釋放。之后pstr_auto再擁有"Long -neck"字符內存的所有權。

    注:reset(0)可以釋放對象,銷毀內存。

    3) release()

    返回auto_ptr指向的那個對象的內存地址,并釋放對這個對象的所有權。

    用此函數初始化auto_ptr時可以避免兩個auto_ptr對象擁有同一個對象的情況(與get函數相比)。

    例子如下:

    auto_ptr< string > pstr_auto( new string( "Brontosaurus" ) );

    auto_ptr< string > pstr_auto2( pstr_auto.get() ); //這是兩個auto_ptr擁有同一個對象

    auto_ptr< string > pstr_auto2( pstr_auto.release() ); //release可以首先釋放所有權

    RFID管理系統集成商 RFID中間件 條碼系統中間層 物聯網軟件集成
    最近免费观看高清韩国日本大全