2008年11月28日 星期五

auto_ptr自動管理配置資源

對於使用new動態配置的資源,在不使用時必須記得delete,以釋放記憶體空間,然而動態記憶體配置很容易發生忘了delete,或是對同一個記憶體位址delete兩次(例如一個物件被指定給兩個指標),或是對一個已經被delete的位址再作讀寫動作。

C++標準函式庫中提供auto_prt,可以協助您動態管理new而建立的物件,要使用auto_prt,您要含入memory表頭檔,例如:

#include <memory>


auto_ptr可以指向一個以new建立的物件,當auto_ptr的生命週期結束後,所指向的物件之資源也會被釋放,在建立auto_ptr時必須指定目標物件之型態,例如:

auto_ptr<int> iPtr (new int(100));
auto_ptr<string> sPtr (new string("caterpillar"));


操作auto_ptr就像操作沒有使用auto_ptr的指標一樣,例如:

cout << *iPtr << endl; // 顯示100
if(sPtr->empty())
  cout << "字串為空" << endl;


您也可以建立一個未指向任何物件的auto_prt,例如:

auto_ptr<int> iPtr;


未指向任何物件的auto_ptr不可以取值,否則會發生不可預期之結果,既然不可取值,如何判斷它是否有指向物件呢?您可以使用get()函式,它會傳回所指向物件的位址,如果傳回0,表示不指向任何物件,如果不指向任何物件,您可以使用reset()來讓它指向一個物件,例如:

if(iPtr.get() == 0) {
  iPtr.reset(new int(100));
}


reset()可以接受一個指標或是0表示不指向任何物件,reset()會先delete目前指向的物件,然後重新指向新的物件,您也可以使用 release()釋放auto_ptr管理所指向物件的職責。

auto_ptr可以使用另一個auto_ptr來建立,這會造成所有權的轉移,例如:
auto_ptr<SafeArray> ptr1(new SafeArray(19));
auto_ptr<SafeArray> ptr2(ptr1);

當使用ptr1來建立ptr2時,ptr1不再對所指向物件的資源釋放負責,職責交給了ptr2,在使用指定運算時,也有類似的行為,例如:
auto_ptr<SafeArray> ptr1(new SafeArray(19));
auto_ptr<SafeArray> ptr2(new SafeArray(20));
ptr2 = ptr1;

ptr2所指向的物件會先被delete,然後ptr1的屬性會複製至ptr2,也就是ptr1所指向的物件,現在由ptr2指向它了,ptr1不再負責所指向物件的資源釋放。

auto_ptr的資源維護動作是以inline的方式來完成,也就是在編譯時會被擴展開來,所以使用auto_ptr並不會犧牲效率。

最後要注意的是,auto_ptr不能用來管理動態配置而來的陣列,如果用它來管理動態配置而來的陣列,結果是不可預期的

我的想法:
使用auto_ptr有兩個角色:
第一個是本身auto_ptr的功能,此時,變數為物件,可以使用.來使用以下函數get()、reset()、release()的功能。
第二個是表示其它物件的指標,用來使用管理的指向物件的職責。

參考資料:
C++ Gossip: auto_ptr 自動管理配置資源

沒有留言: