雖然花了兩篇介紹 std::unique_ptr<T>
,但其實還沒把全部的好處以及可用的場景交代清楚,山姆大叔未來還有其他規劃,這篇的主角改由 std::shared_ptr<T>
上場。進入正題前,照慣例岔一下題。
新手學習 C++,多從「語法」開始學起。把握了基本組件的寫法之後,開始組合建構需要的功能。累積了足夠的經驗,便能觀察出程式碼的「語義」——「這個迴圈的用意是找出最大值」、「這裡使用繼承是為了模塑該領域的模型」。從比較高的層次理解程式碼,是新手養成專家必須學會的重要技能。
初接觸 std::unique_ptr<T>
,先懂其語法,之後試著用 std::unique_ptr<T>
取代原本的指標,搭配 std::make_unique
,終極目標是讓 new/delete 消失。但是,有些情況 std::unique_ptr<T>
無法定義適當的語義,例如「一個指標被多方使用的場景」,這時候便輪到 std::shared_ptr<T>
上場。
顧名思義,std::shared_ptr<T>
提供一個介面,讓同一個物件或資源被多個用戶端使用,其管理的物件會在沒有任何用戶端時刪除。判斷物件何時應被不是透過 GC,而是利用「參用計數」,當參考到該物件的用戶數為零時,刪除之。
COM 管理物件的方式也是使用了「參用計數」,其 IUnknown 介面中的 AddRef/Release 用來確保物件不再有任何人參考時,自動刪除。
std::shared_ptr<T>
定義了一個明確的「語義」:多數情況下,使用 std::shared_ptr<T>
不應該,也不用知道物件何時會被刪除。底下示範一個簡單的 std::shared_ptr<T>
用法:
std::shared_ptr<TeaShopOwner> owner = std::make_shared<TeaShopOwner>();
std::shared_ptr<TeaShopOwner> ccp_owner = owner;
try {
ccp_owner->SetOneCountryTwoSystem(true);
}
catch (const Never& e) {
}
上述的 owner
以及 cpp_owner
操作的是同一個物件,雙雙離開 scope 後,其管理的物件才即被刪除。