1. 程式人生 > >智慧指標的引入——定義一個行為像指標的類(point like class)

智慧指標的引入——定義一個行為像指標的類(point like class)

定義一個行為像指標的類(point like class)

在C++智慧指標share_ptr之所以能夠比較智慧的進行資源的動態分配和回收,一個非常非常重要的概念就是引入了引用計數。智慧指標不僅僅是一個裸指標,而是一個行為像指標的類。

所謂的引用計數的工作原理,有以下四點:

當我們建立一個物件時,只有一個物件共享狀態,所以我們把當前物件的引用計數置為一。

拷貝建構函式不分配新的計數器,而是拷貝給定的物件的資料成員,並且包括計數器,兩者共享一個計數器,因為給定的物件的共享狀態多了一個,所以遞增共享計數器。

解構函式遞減計數器,如果當前的計數器值遞減後為零,則解構函式釋放改給定物件。

拷貝賦值運算子遞增右側物件的計數器,遞減左側物件的計數器,如果左側的物件的計數器被遞減為零,就釋放掉該物件。

我們引用這樣的計數原理,就能更好的管理資源的分配了。接下來,我們便定義一個自己的簡單的smart_ptr,來看看這個引用計數到底應該怎麼寫。

class smartptr{
public:
  smartptr(const std::string &s=std::string()):
     ps(new std::string(s)),i(0),use(new std::size_t(1)){}
  smartptr(const smartptr &p):
     ps(p.ps),i(p.i),use(p.use){ *use++;}
  smartptr& operator=(const smartptr&);
  ~smartptr();
private:
  std::string *ps;
  int i;
  std::size_t *use;
};
smartptr::~smartptr(){
  if(--*use==0){
     delete ps;
     delete use;
  }
}
smartptr& smartptr::oprator=(const smartptr &temp){
   ++*temp.use;
   if(--*use==0){
     delete ps;
     delete use;
   use=temp.use;
   ps=temp.ps;
   i=temp.i;
   return *this;
}

上面的程式碼很好理解,基本上就是對引用計數的實現,程式碼中的size_t資料型別需要注意一下,相比用int計數,size_t更容易移植,在32位編譯系統中,size_t佔4個位元組,在64位系統中,size_t佔8個位元組。

在vc++中,size_t的定義如下:

  1. #ifdef _WIN64

  2. typedef unsigned __int64 size_t;

  3. #else

  4. typedef _W64 unsigned int size_t;

  5. #endif

大概的意思就是說size_t的型別要麼是unsigned long int,要麼是unsigned int。

使用size_t能夠大大的提高程式碼的可移植性,有效性和可讀性。

在標準C庫中的許多函式使用的引數或者返回值都是表示的用位元組表示的物件大小,比如說malloc(n) 函式的引數n指明瞭需要申請的空間大小,還有memcpy(s1, s2, n)的最後一個引數,表明需要複製的記憶體大小,strlen(s)函式的返回值表明了以'\0'結尾的字串的長度(不包括'\0'),其返回值並不是該字串的實際長度,因為要去掉'\0'。

今後有時間會對這個用位元組表示物件大小的size_t進行解析。