本文主要討論c++程式設計的一種常用技術——智慧型指標(smart pointer),主要內容包括引用計數(reference count)和控制代碼類(handle class)。如果文中有錯誤或遺漏之處,敬請指出,謝謝!
當類中有指標成員時,一般有兩種方式來管理指標成員:一是採用值型的方式管理,每個類物件都保留乙份指標指向的物件的拷貝;另一種更優雅的方式是使用智慧型指標,從而實現指標指向的物件的共享。
智慧型指標(smart pointer)的一種通用實現技術是使用引用計數(reference count)。智慧型指標類將乙個計數器與類指向的物件相關聯,引用計數跟蹤該類有多少個物件共享同一指標。
每次建立類的新物件時,初始化指標並將引用計數置為1;當物件作為另一物件的副本而建立時,拷貝建構函式拷貝指標並增加與之相應的引用計數;對乙個物件進行賦值時,賦值操作符減少左運算元所指物件的引用計數(如果引用計數為減至0,則刪除物件),並增加右運算元所指物件的引用計數;呼叫析構函式時,建構函式減少引用計數(如果引用計數減至0,則刪除基礎物件)。
實現引用計數有兩種經典策略:一是引入輔助類,二是使用控制代碼類。下面分別介紹這些內容。
問題描述
假設有乙個名為testptr的類,裡面有乙個指標成員,簡化為如下**:
class testptr
~testptr( )
// other operations
private:
int *ptr;
// other data
};
在這種情況下,類testptr物件的任何拷貝、賦值操作都會使多個testptr物件共享相同的指標。但在乙個物件發生析構時,指標指向的物件將被釋放,從而可能引起懸垂指標。
現在我們使用引用計數來解決這個問題,乙個新的問題是引用計數放在**。顯然,不能放在testptr類中,因為多個物件共享指標時無法同步更新引用計數。
方案一
這裡給出的解決方案是,定義乙個單獨的具體類(refptr)來封裝指標和相應的引用計數。由於這個類只是用於對類testptr中的成員指標ptr進行了封裝,無其它用途,所以把引用計數類refptr的所有成員均定義為private,並把類testptr宣告為它的友元類,使testptr類可以訪問refptr類。示例**如下:
class refptr
~refptr ()
};class testptr
testptr(const testptr& src): ptr(src.ptr)
testptr& operator= (const testptr& rhs)
~testptr()
private:
refptr *ptr;
};
當希望每個testptr物件中的指標所指向的內容改變而不影響其它物件的指標所指向的內容時,可以在發生修改時,建立新的物件,並修改相應的引用計數。這種技術的乙個例項就是寫時拷貝(copy-on-write)。
這種方案的缺點是每個含有指標的類的實現**中都要自己控制引用計數,比較繁瑣。特別是當有多個這類指標時,維護引用計數比較困難。
方案二
為了避免上面方案中每個使用指標的類自己去控制引用計數,可以用乙個類把指標封裝起來。封裝好後,這個類物件可以出現在使用者類使用指標的任何地方,表現為乙個指標的行為。我們可以像指標一樣使用它,而不用擔心普通成員指標所帶來的問題,我們把這樣的類叫控制代碼類。在封裝控制代碼類時,需要申請乙個動態分配的引用計數空間,指標與引用計數分開儲存。實現示例如下:
#include
#include
using namespace std;
#define test_smartptr
class stub
smartptr(const smartptr& src): ptr(src.ptr), puse(src.puse)
smartptr& operator= (const smartptr& rhs)
t *operator->()
const t *operator->() const
t &operator*()
const t &operator*() const
~smartptr()
private:
void decruse()
}t *ptr;
size_t *puse;
};int main()
catch (const exception& err)
//運算子過載,實現了操作指標就和操作物件相同
c 智慧型指標 C 智慧型指標是如何實現的
c 程式執行時,計算機記憶體從大類上分為棧和堆,在棧上的記憶體是由系統自動分配和 的,而堆上的記憶體卻是由程式設計師手動申請和釋放的,如果程式設計師在記憶體的管理上出現失誤,輕則程式執行結果與預期有差距,重則程式直接崩潰 棧和堆記憶體 區別 棧記憶體上的變數在過了作用域 大括號 後系統會自動 而堆記...
C 智慧型指標實現
1 問題的提出 先看下面的例子 class ctext ctext private int m ptr int funtext 在函式funtext 中,類的兩個物件共用了new出來的指標ptr。當函式執行開始時,呼叫兩次建構函式 退出執行時,呼叫兩次析構函式,而在第一次呼叫時已經delete pt...
智慧型指標實現C
include using namespace std template class shared ptrelse shared ptr const shared ptr ptr shared ptr operator const shared ptr ptr if this ptr this pt...