上一篇:http://www.BkJia.com/kf/201112/115672.html
17.1.9 auto_ptr類
auto_ptr類在頭文件memory中定義。
auto_ptr只能用於管理從new返回的一個對象,它不能管理動態分配的數組。
正如我們所見,當auto_ptr被復制或賦值的時候,有不同尋常的行為,因此,不能將auto_ptr存儲在標准庫容器類型中。
每個auto_ptr對象綁定到一個對象或者指向一個對象。當auto_ptr對象指向一個對象的時候,可以說它“擁有”該對象。當auto_ptr對象超出作用域或者另外撤銷的時候,就自動回收auto_ptr所指向的動態內存對象。
1. 為異常安全的內存分配使用auto_ptr
auto_ptr<int> i(new int(42)); //auto_ptr manage int* i...
throw exception();
auto_ptr<int> i(new int(42)); //auto_ptr manage int* i...
throw exception();2. auto_ptr是可以保存任何類型指針的模板
auto_ptr類是接受某個單個類型形參的模板,該類型指定auto_ptr可以綁定的對象的類型,因此,可以創建任何類型的auto_ptr。
3. 將auto_ptr綁定到指針
接受指針的構造函數為explicit構造函數,所以必須使用初始化的直接形式來創建auto_ptr對象。
4. 使用auto_ptr對象
auto_ptr<string> i(new string("42")); //auto_ptr manage string* i...
//throw exception();
cout<<*i<<endl;
cout<<i->length()<<endl;
auto_ptr<string> i(new string("42")); //auto_ptr manage string* i...
//throw exception();
cout<<*i<<endl;
cout<<i->length()<<endl;auto_ptr的主要目的是,在保證自動刪除auto_ptr對象引用的對象的同時,支持普通指針式行為。正如我們所見,自動刪除該對象這一事實導致在怎樣復制和訪問它們的地址值方面,auto_ptr與普通指針明顯不同。
5. auto_ptr對象的復制和賦值是破壞性操作
auto_ptr和內置指針對待復制和賦值有非常關鍵的重要區別。當復制auto_ptr對象或者將它的值賦給其他auto_ptr對象的時候,將基礎對象的所有權從原來的auto_ptr對象轉給副本,原來的auto_ptr對象重置為未綁定狀態。
與其他復制或賦值操作不同,auto_ptr的復制和賦值改變右操作數,因此,賦值的左右操作數必須都是可修改的左值。
6. 賦值刪除左操作數指向的對象
除了將所有權從右操作數轉給左操作數之外,賦值還刪除左操作數原來指向的對象——假如兩個對象不同。通常自身賦值沒有效果。
因為復制和賦值時破壞性操作,所以不能將auto_ptr對象存儲在標准容器中。標准庫的容器類要求復制或賦值之後兩個對象相等,auto_ptr不滿足這一要求。
7. auto_ptr的默認構造函數
如果不給頂初始式,auto_ptr對象是未綁定的,它不指向對象。
默認情況下,auto_ptr的內部指針值置為0。對未綁定的auto_ptr對象解引用,其效果與對未綁定的指針解引用相同——程序出錯而且沒有定義會發生什麼。
8. 測試auto_ptr對象
為了檢查指著是否未綁定,可以在條件中直接測試指針,效果是確定指針是否為0.相反,不能直接測試auto_ptr對象。
auto_ptr類型沒有定義到可用作條件的類型的轉換,相反,要測試auto_ptr對象,必須使用它的get成員,該成員包含在auto_ptr對象中的基礎指針。
auto_ptr<string> i(new string("42")); //auto_ptr manage string* i...
//throw exception();
if(i.get()){
cout<<*i<<endl;
cout<<i->length()<<endl;
}
auto_ptr<string> i(new string("42")); //auto_ptr manage string* i...
//throw exception();
if(i.get()){
cout<<*i<<endl;
cout<<i->length()<<endl;
}為了確定auto_ptr是否指向一個對象,可以將get的返回值與0比較。
應該只用get詢問auto_ptr對象或者使用返回的指針值,不能用get作為創建其他auto_ptr對象的實參。
使用get成員初始化其他auto_ptr對象違反auto_ptr類設計原則:在任意時刻只有一個auto_ptr對象保存給定指針,如果兩個auto_ptr對象保存相同的指針,該指針就會被delete兩次。
9. reset操作
auto_ptr對象與內置指針的另一個區別是,不能直接將一個地址(或者其他指針)賦給auto_ptr對象,相反,必須調用reset函數來改變指針。
調用auto_ptr函數對象的reset函數時,在將auto_ptr對象綁定到其他對象之前,會刪除auto_ptr對象所指向的對象(如果存在)。但是,正如自身賦值是沒有效果的一樣,如果調用該auto_ptr對象已經保存的同一指針的reset函數,也沒有效果,不會刪除對象。
auto_ptr<string> i(new string("42")); //auto_ptr manage string* i...
//throw exception();
if(i.get()){
i.reset(new string("Anders"));
cout<<*i<<endl; //Anders
cout<<i->length()<<endl; //6
}
摘自 xufei96的專欄