程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> 第17章 用於大型程序的工具(5)

第17章 用於大型程序的工具(5)

編輯:C++入門知識

上一篇: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的專欄
 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved