這裡先介紹auto_ptr的缺陷:
因為auto_ptr並不是完美無缺的,它的確很方便,但也有缺陷,在使用時要注意避免。首先,不要將auto_ptr物件作為stl容器的元素。c++標準明確禁止這樣做,否則可能會碰到不可預見的結果
auto_ptr的另乙個缺陷是將陣列作為auto_ptr的引數: auto_ptr pstr (new char[12] ); //陣列;為定義
然後釋放資源的時候不知道到底是利用delete pstr,還是 delete pstr;
然後收集了關於auto_ptr的幾種注意事項:
1、auto_ptr不能共享所有權。
2、auto_ptr不能指向陣列
3、auto_ptr不能作為容器的成員。
4、不能通過賦值操作來初始化auto_ptr
std::auto_ptr p(new int(42)); //ok
std::auto_ptr p = new int(42); //error
這是因為auto_ptr 的建構函式被定義為了explicit
5、不要把auto_ptr放入容器
auto_ptr是c++標準庫提供的類模板,auto_ptr物件通過初始化指向由new建立的動態記憶體,它是這塊記憶體的擁有者,一塊記憶體不能同時被分給兩個擁有者。當auto_ptr物件生命週期結束時,其析構函式會將auto_ptr物件擁有的動態記憶體自動釋放。即使發生異常,通過異常的棧展開過程也能將動態記憶體釋放。auto_ptr不支援new陣列。
#include
1) 建構函式
1] 將已存在的指向動態記憶體的普通指標作為引數來構造
int* p = new int(33);
auto_ptr api(p);
2] 直接構造智慧型指標
auto_ptr< int > api( new int( 33 ));
2) 拷貝構造
利用已經存在的智慧型指標來構造新的智慧型指標
auto_ptr< string > pstr_auto( newstring( "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不再被用來指向該物件。
通常的指標在定義的時候若不指向任何物件,我們用null給其賦值。對於智慧型指標,因為建構函式有預設值0,我們可以直接定義空的auto_ptr如下:
auto_ptr< int >p_auto_int; //不指向任何物件
因為auto_ptr的所有權獨有,所以下面的**會造成混亂。
int* p = new int(0);
auto_ptr ap1(p);
auto_ptr ap2(p);
因為ap1與ap2都認為指標p是歸它管的,在析構時都試圖刪除p, 兩次刪除同乙個物件的行為在c++標準中是未定義的。所以我們必須防止這樣使用auto_ptr。
1)按值傳遞時,函式呼叫過程中在函式的作用域中會產生乙個區域性物件來接收傳入的auto_ptr(拷貝構造),這樣,傳入的實參auto_ptr就失去了其對原物件的所有權,而該物件會在函式退出時被區域性auto_ptr刪除。如下例:
void f(auto_ptr ap)
{cout<
auto_ptr ap1(new int(0));
f(ap1);
cout<
2)引用或指標時,不會存在上面的拷貝過程。但我們並不知道在函式中對傳入的auto_ptr做了什麼,如果當中某些操作使其失去了對物件的所有權,那麼這還是可能會導致致命的執行期錯誤。
結論:const reference是智慧型指標作為引數傳遞的底線。
原因很簡單,delete 表示式會被應用在不是動態分配的指標上這將導致未定義的程式行為。
1) get()
返回auto_ptr指向的那個物件的記憶體位址。如下例:
int* p = new int(33);
cout << "the adress of p:"<< p<< endl;
auto_ptr ap1(p);
cout << "the adress of ap1: "<< &ap1<< endl;
cout << "the adress of the objectwhich 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( newstring( "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( newstring( "brontosaurus" ) );
auto_ptr< string > pstr_auto2(pstr_auto.get() ); //這是兩個auto_ptr擁有同乙個物件
auto_ptr< string > pstr_auto2(pstr_auto.release() ); //release可以首先釋放所有權
c 智慧型指標
auto prt 它是 它所指向物件的擁有者 所以當自身物件被摧毀時候,該物件也將遭受摧毀,要求乙個物件只有乙個擁有者,注意 auto prt 不能使用new 來分配物件給他 include include using namespace std template void bad print au...
c 智慧型指標
很久沒寫部落格了,不知道如何表達了,哈哈.我先介紹一下深淺拷貝.class copy 此時a.ptr和b.ptr指向同乙個物件,當我們delete a.ptr時 b.ptr所指向的物件已經不存在了,要是我們引用b.ptr指向的物件也就會出問題了.深拷貝 把a.ptr所指向的物件拷貝乙份給b.ptr ...
c 智慧型指標
記得前不久有一次面試被問到智慧型指標的實現,當時對智慧型指標只是聽說但沒有了解過,就亂七八糟地說了一遍。今天寫了一遍智慧型指標,用了引用計數的概念。主要思想就是,用乙個新類對原本需要的型別進行了一層封裝,這個新類中儲存了原本的物件指標和乙個引用計數的指標,之所以全部用指標來儲存,就是因為會出現多個新...