關于shared_ptr

簡單總結族操,詳見參考資料肝匆。

引用計數(shù)的實現(xiàn)方式

引用計數(shù)是與對象綁定的坛悉,并且可能有多個shared_ptr綁定同一對象,為了達到同時更新多個shared_ptr的引用計數(shù)台颠,所以需要讓他們指向同一個引用計數(shù)褐望,所以只能在堆上另外分配空間來存放引用計數(shù)。
為了保證多線程讀同一個shared_ptr是安全的串前,引用計數(shù)的增減是原子操作瘫里。

線程安全性

shared_ptr 的線程安全級別和內建類型、標準庫容器荡碾、std::string 一樣谨读,即:
一個 shared_ptr 對象實體可被多個線程同時讀取坛吁;
兩個 shared_ptr 對象實體可以被兩個線程同時寫入劳殖,“析構”算寫操作铐尚;
如果要從多個線程讀寫同一個 shared_ptr 對象,那么需要加鎖哆姻;

為什么shared_ptr不能并發(fā)讀寫:因為 shared_ptr 有兩個數(shù)據(jù)成員(引用計數(shù)宣增、對象指針),讀寫操作不能原子化矛缨。
具體發(fā)生多線程問題的場景可以自己推導爹脾,更詳細的說明可以看陳碩寫的文章:
為什么多線程讀寫 shared_ptr 要加鎖?

enable_shared_from_this的實現(xiàn)

一個主要的場景是保證異步回調函數(shù)中操作的對象仍然有效箕昭。
std::enable_shared_from_this<T> 有一個std::weak_ptr<T>的成員灵妨,實際上在構造std::enable_shared_from_this<T>時,并沒有初始化std::weak_ptr<T>成員落竹,而是在用這個std::enable_shared_from_this<T>去構造std::shared_ptr的時候泌霍,去構造并初始化這個std::weak_ptr<T>成員。所以這也就是為什么cppreference中說的這個對象必須是std::shared_ptr管理的述召,因為這個對象不是通過std::shared_ptr來管理烹吵,那么std::weak_ptr是未初始化的,無法通過其提升為std::shared_ptr對象桨武。
如何判斷是否繼承了shared_from_this?模板類型推導:根據(jù)是否有繼承特定類型實例化不同的模板實現(xiàn)肋拔;
多繼承場景下使用虛繼承解決問題;

make_shared/new

與直接使用new相比呀酸,make函數(shù)不存在代碼重復且具備異常安全性凉蜂,std::make_shared和std::allocate_shared可以生成更快更短的目標碼。
對象和控制塊分配在一塊內存上性誉,減少了內存分配的次數(shù)窿吩。但是這并不一定是好事,因為這導致對象和控制塊占用的內存也要一次回收掉错览。即纫雁,如果還有std::weak_ptr存在,控制塊就要在倾哺,對象占用的內存也沒辦法回收轧邪。如果對象比較大,且std::weak_ptr在對象析構后還可能長期存在羞海,那么這種開銷是不可忽視的忌愚。
在需要自定義刪除器及以大括號初始化時make函數(shù)無能為力。
更詳細可以閱讀《Effective Moden C++》Item 21却邓。

pointer_cast的實現(xiàn)

智能指針的類型轉換無法通過static_cast等實現(xiàn)硕糊,需要使用static_pointer_cast方法(想一下如果取裸指針出來static_cast會發(fā)生什么)。static_pointer_cast是通過shared_ptr一個特殊的構造函數(shù)實現(xiàn)的。

template< class T, class U > 
std::shared_ptr<T> static_pointer_cast( const std::shared_ptr<U>& r ) noexcept
{
    auto p = static_cast<typename std::shared_ptr<T>::element_type*>(r.get());
    return std::shared_ptr<T>(r, p);
}

shared_ptr與deleter

shared_ptr<Foo> sp(new Foo)在構造sp的時候捕獲了Foo的析構行為简十,意味著:

  1. shared_ptr<void> 可以指向并安全地管理(析構或防止析構)任何對象檬某,派生類沒有虛析構函數(shù)也能被正確析構

    shared_ptr<Foo> sp1(new Foo); // ref_count.ptr 的類型是 Foo*
    shared_ptr<void> sp2 = sp1; // 可以賦值,F(xiàn)oo* 向 void* 自動轉型
    sp1.reset(); // 這時 Foo 對象的引用計數(shù)降為 1

此后 sp2 仍然能安全地管理 Foo 對象的生命期螟蝙,并安全完整地釋放 Foo恢恼,不會出現(xiàn) delete void* 的情況,因為 delete 的是 ref_count.ptr胶逢,不是 sp2.ptr。
std::shared_ptr<void>的工作原理

  1. shared_ptr進行資源銷毀時饰潜,總會調用創(chuàng)建智能指針的那個DLL中的delete初坠,這意味著shared_ptr可以隨意地在DLL間傳遞而不需擔心跨DLL的問題。(Effective C++ Item18)

參考資料:
為什么多線程讀寫 shared_ptr 要加鎖
std::shared_ptr<void>的工作原理
《Effective C++》
《Effective Modern C++》

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末彭雾,一起剝皮案震驚了整個濱河市碟刺,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌薯酝,老刑警劉巖半沽,帶你破解...
    沈念sama閱讀 206,602評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異吴菠,居然都是意外死亡者填,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,442評論 2 382
  • 文/潘曉璐 我一進店門做葵,熙熙樓的掌柜王于貴愁眉苦臉地迎上來占哟,“玉大人,你說我怎么就攤上這事酿矢≌ズ酰” “怎么了?”我有些...
    開封第一講書人閱讀 152,878評論 0 344
  • 文/不壞的土叔 我叫張陵瘫筐,是天一觀的道長蜜暑。 經常有香客問我,道長策肝,這世上最難降的妖魔是什么肛捍? 我笑而不...
    開封第一講書人閱讀 55,306評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮之众,結果婚禮上篇梭,老公的妹妹穿的比我還像新娘。我一直安慰自己酝枢,他們只是感情好恬偷,可當我...
    茶點故事閱讀 64,330評論 5 373
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著帘睦,像睡著了一般袍患。 火紅的嫁衣襯著肌膚如雪坦康。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,071評論 1 285
  • 那天诡延,我揣著相機與錄音滞欠,去河邊找鬼。 笑死肆良,一個胖子當著我的面吹牛筛璧,可吹牛的內容都是我干的。 我是一名探鬼主播惹恃,決...
    沈念sama閱讀 38,382評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼夭谤,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了巫糙?” 一聲冷哼從身側響起朗儒,我...
    開封第一講書人閱讀 37,006評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎参淹,沒想到半個月后醉锄,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經...
    沈念sama閱讀 43,512評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡浙值,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 35,965評論 2 325
  • 正文 我和宋清朗相戀三年恳不,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片开呐。...
    茶點故事閱讀 38,094評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡妆够,死狀恐怖,靈堂內的尸體忽然破棺而出负蚊,到底是詐尸還是另有隱情神妹,我是刑警寧澤,帶...
    沈念sama閱讀 33,732評論 4 323
  • 正文 年R本政府宣布家妆,位于F島的核電站鸵荠,受9級特大地震影響,放射性物質發(fā)生泄漏伤极。R本人自食惡果不足惜蛹找,卻給世界環(huán)境...
    茶點故事閱讀 39,283評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望哨坪。 院中可真熱鬧庸疾,春花似錦蛛株、人聲如沸业踢。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,286評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至金顿,卻和暖如春臊泌,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背揍拆。 一陣腳步聲響...
    開封第一講書人閱讀 31,512評論 1 262
  • 我被黑心中介騙來泰國打工渠概, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人嫂拴。 一個月前我還...
    沈念sama閱讀 45,536評論 2 354
  • 正文 我出身青樓播揪,卻偏偏與公主長得像,于是被迫代替她去往敵國和親筒狠。 傳聞我的和親對象是個殘疾皇子猪狈,可洞房花燭夜當晚...
    茶點故事閱讀 42,828評論 2 345