句柄類

句柄類(智慧型指針smart point)是存儲指向動態分配(堆)對象指針的類。

句柄類定義

一般定義

句柄類(智慧型指針smart point)是存儲指向動態分配(堆)對象指針的類。除了能夠在適當的時間自動刪除指向的對象外,他們的工作機制很像C++的內置指針。智慧型指針在面對異常的時候格外有用,因為他們能夠確保正確的銷毀動態分配的對象。他們也可以用於跟蹤被多用戶共享的動態分配對象。

在C++中一個通用的技術是定義包裝(cover)類或句柄(handle)類,也稱智慧型指針。句柄類存儲和管理基類指針。指針所指向對象的類型可以變化,它既可以指向基類類型對象又可以指向派生類型對象。用戶通過句柄類訪問繼承層次的操作。因為句柄類使用指針執行操作,虛成員的行為將在運行時根據句柄實際綁定的對象類型而變化,即實現c++運行時動態綁定。故句柄用戶可以獲得動態行為但無需操心指針的管理。

理解實質

句柄類實際上通過複製指向引用計數器類型的指針,來代替複製實際對象;從而使得複製對象變成複製指針,實現虛擬複製(即是用複製對象的地址代替複製對象本身),以提高記憶體效率和訪問速度。在涉及到大型、複雜對象以及一些不能複製或是不易複製的對象的複製控制問題時,顯得特別有用。

句柄類涉及的技術

引入使用計數

定義句柄類或智慧型指針的通用技術是採用一個使用計數(use count)。句柄類將一個計數器與類指向的對象相關聯。使用計數跟蹤該類有多少個指針共享同一對象。當使用計數為0時,就刪除該類對象,否則再刪除類對象時,只要引用計數不為0,就不刪除實際的類對象,而是是引用計數減1,實現虛刪除。

使用計數類

為了便於理解,我們定義一個實際類(Point),一個引用計數器類(UPoint),一個句柄類(Handle),後面將有例子給以參考。

實現使用計數有兩種經典策略:一種是定義一個單獨的具體的類用以封裝使用計數和指向實際類的指針;

另一種是定義一個單獨的具體的類用以封裝引用計數和類的對象成員。我們稱這種類為計數器類(UPoint)。在計數器類中,所有成員均設定為private,避免外部訪問,但是將句柄類Handle類聲明為自己的友元,從而使句柄類能操縱引用計數器。

寫時複製

寫時複製(copy on write)技術是解決如何保證要改動的那個引用計數器類UPoint對象不能同時被任何其他的句柄類(Handle類)所引用。通俗的來說,就是當實際對象Point被多個Handle類的指針共享時,如果需要通過指針改變實際對象Point,而其他的指針又需要保持原來的值時,這就有矛盾了。打個不恰當的比方來說,兩個以上的人共有5W塊錢,如果其中一個人想用這5W塊錢去消費,那就必須通知其他人。否則在這個人消費了5塊錢後,其他人還以為他們仍然有5W塊錢,如果這兒時候,他們去買5W的東西,就會發現錢變少了或是沒有了,此時他們就陷入債務的泥團。在C++中通過指針訪問已經刪除或是不存在的對象,將是非常危險的。有可能系統提示該行為未定義,也有可以記憶體非法訪問,還有可能使系統崩潰。

句柄類的實例

完成源碼程式

運行結果分析

handle::h 23 34

handle::tmp 23 34 //h和tmp句柄類對象實際共享同一Point(23,34)對象;

handle::val 0 0 //val默認指向實際對象Point(0,0);

~UPoint! //由於寫時複製時:up = new UPoint(up->p);創建了一個臨時UPoint

~Point! //對象;調用完後釋放,由於Point是UPoint的成員對象,所以先

//UPoint,然後是Point。

handle::h 100 34 //通過修改賦值val = h.x(100);後,h和val共享同一對象Point(100,34)

handle::tmp 23 34

handle::val 100 34

//依次釋放記憶體;

~Handle! //val句柄類對象;val(100,34)

~UPoint!

~Point!

~Handle! //tmp句柄類;tmp(23,34)

~UPoint!

~Point!

~Handle! //只釋放了一個句柄類Handle的指針,沒有實際對象;

請按任意鍵繼續. . .

與句柄類相關的類

代理(surrogate)類,又稱委託。(後續完善 )

這篇關於句柄類的介紹,在理論部分還是挺不錯的,但舉的例子就不敢恭維了,UPoint類的目的是從Handle類中將“引用計數”功能分離出來單獨實現,讓Handle類專注於實現“記憶體管理”功能,因此UPoint類必須能夠實現自動計數,而不應該在Handle類中再來對其加減。

上面分析結果的最後一段:

~Handle! //val句柄類對象;val(100,34) ~UPoint! ~Point! ~Handle! //tmp句柄類;tmp(23,34) ~UPoint! ~Point! ~Handle! //只釋放了一個句柄類Handle的指針,沒有實際對象; 請按任意鍵繼續. . .

分析有誤,改為:

~Handle! //val句柄類對象;val(100,34)

~UPoint! //temp指向的UPoint對象

~Point! //temp指向的UPoint對象的內嵌Point對象

~Handle! //tmp句柄類;tmp(23,34)

~UPoint! //val和h共同指向的Upoint對象

~Point! //val和h共同指向的Upoint對象的內嵌對象Point

~Handle! //釋放h句柄類

句柄類例子

相關詞條

熱門詞條

聯絡我們