[問題] std::shared_ptr 與 std::weak_ptr 的使用方式?
最近想試著使用 std::shared_ptr 到新的程式碼中, 但是遇到一些
使用上的困擾, 尤其是 std::weak_ptr 的使用方式.
我有大略看過之前版友分享的影片, 可是對於 std::weak_ptr 的使
用依舊沒有具體概念.
先說明一下我對 std::shared_ptr 的使用認知:
- #include <memory>
- 使用 std::make_shared 建構 std::shared_ptr 以增進效率
- 建構 std::shared_ptr 的方式主要有二:
+ 接受一個『剛 new 出來』的裸指標
(建議使用 std::make_shared 替代)
+ 賦值為其他的 std::shared_ptr
- std::shared_ptr 不應指向一個 new 出來的 C 風格陣列, 建議使
用 std::array 替代. 如果堅持要用 C 風格陣列的話要另外傳入
特製的陣列解構函式.
- 需要在某類別內取得該類別物件的 std::shared_ptr 時,該類別
需繼承 std::enable_shared_from_this,之後我們可以用
shared_from_this 這個繼承的成員函式去取得。
- 避免使用 std::shared_ptr::get() 去獲得裸指標
- 使用 std::static_pointer_cast、std::dynamic_pointer_cast 及
std::const_pointer_cast 去對 std::shared_ptr 轉型
大致上 std::shared_ptr 的使用我覺得應該是蠻單純的. 但是在
std::weak_ptr 的使用方式上, 我目前的認知是:
- #include <memory>
- 從一個 std::weak_ptr 或 std::shared_ptr 建構 std::weak_ptr
- std::weak_ptr 的使用時機:
- 當我們對指標指向的物件之生命週期不需要有控制權的時候使用:
+ 可能只是想觀測指向同一物件的 std::shared_ptr 個數
+ 可能邏輯上所指向的物件可以是存在或不存在的情況
- 當我們要解決 std::shared_ptr 的『循環參考』的問題時使用:
如果我們把所有的 std::shared_ptr 跟底層物件的指向關係畫
成一個圖. 則該圖需要是個 DAG (Directed acyclic graph),
否則會有記憶體洩漏 (memory leak) 的風險。
要將一個不是 DAG 的圖改成 DAG 的方式是利用 std::weak_ptr
去取代 std::shared_ptr 來解除圖中的循環 (cycle)。
只是要把哪些 std::shared_ptr 取代成 std::weak_ptr 是需要
設計過的.
std::weak_ptr 所間接指向的物件必須不比 std::weak_ptr 本身
的生命週期短。否則 std::weak_ptr 可能會間接指向一個已經
死亡的物件,而無法取代原本 std::shared_ptr 的用途。
但是該間接參考的物件的死亡時間又是由指向該物件的所有
std::shared_ptr 所共同決定。
簡言之, 我們在將一個原有的圖改成 DAG 時,用 std::weak_ptr
所取代的 std::shared_ptr 所指向的物件,必須不能比該
std::weak_ptr 早死亡。也就是說指向該物件的 std::shared_ptr
中至少要有一個不會比該 std::weak_ptr 早死亡。
如何確保這件事情發生感覺有點複雜阿....
我想到的三種解法:
+ 畫出圖後找到出現在循環中的所有物件,找出所有指向循環中的
物件而不在循環中的 std::shared_ptr 裡有最長生命週期的。
將循環中指向該物件的 std::shared_ptr 改為 std::weak_ptr
+ 額外產生一個最晚死亡的 std::shared_ptr 去指向某循環中的
物件。將循環中指向該物件的 std::shared_ptr 改為
std::weak_ptr。
+ 在有可能出現循環的程式中放棄 std::shared_ptr 的使用
不曉得有沒有什麼方式讓我們容易判斷?或者是我認知上有什麼問
題嗎 Q_Q
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 140.112.29.148
※ 編輯: Feis 來自: 140.112.29.148 (01/30 21:07)
→
01/30 21:23, , 1F
01/30 21:23, 1F
→
01/30 21:23, , 2F
01/30 21:23, 2F
→
01/30 21:29, , 3F
01/30 21:29, 3F
→
01/30 21:29, , 4F
01/30 21:29, 4F
→
01/30 21:30, , 5F
01/30 21:30, 5F
→
01/30 21:31, , 6F
01/30 21:31, 6F
→
01/30 21:31, , 7F
01/30 21:31, 7F
我加了一行字也許可以減少些誤會.
※ 編輯: Feis 來自: 140.112.29.148 (01/31 03:03)
討論串 (同標題文章)
C_and_CPP 近期熱門文章
PTT數位生活區 即時熱門文章