看板 C_and_CPP 關於我們 聯絡資訊
可以自由傳遞指標的 std::shared_ptr 比傳統指標要安全許多 但即使如此也還是有cyclic reference的問題存在 網路上查到的解法幾乎都用 weak_ptr 來處理 但是我怎麼看都不覺得這算解法 因為它無法阻止物件被釋放 之所以要使用 std::shared_ptr 就是希望抓著指標就一定能使用所指的物件 我自己目前的做法是對物件分層級 只有高層物件可以擁有指標指向下層物件 確保不會連成一圈 這方式我還沒看到明顯的問題 但是這種自我約束的行為還是很不可靠 一個不小心包成std::function之類的東西然後亂丟可能就發生 而且一旦出現cyclic也很難查覺 因為它就只是安靜的咬著記憶體不放 不知道有沒有更理想的處理方式? 或者有比 shared_ptr 更好的工具也可以介紹一下 -- ※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 118.167.53.99 (臺灣) ※ 文章網址: https://www.ptt.cc/bbs/C_and_CPP/M.1560589812.A.F19.html
loveme00835: 你怎麼不先從設計開始討論?會用到 std::shared_ptr 06/15 19:08
loveme00835: 大部分情況就是懶得好好設計 06/15 19:08
不用shared_ptr的話,物件不就只能活在一個scope裡面而已了嗎? 另外std::function要有closure效果的話也是綁shared_ptr比較安全 很難不使用啊 ※ 編輯: eye5002003 (118.167.53.99 臺灣), 06/15/2019 20:53:47
loveme00835: 你有好好釐清 ownership 嗎? 06/16 00:00
loveme00835: std::shared_ptr 的 share 是 share responsibility 06/16 00:02
loveme00835: 不是 share object, 首先為了 share object 用 06/16 00:03
loveme00835: std::shared_ptr 就算是誤用, 為了讓 std::function 06/16 00:04
loveme00835: own object 你有必須這樣做的理由嗎? 還是 lifetime 06/16 00:04
loveme00835: 還沒分析過就直接用了? 06/16 00:05
不管是share什麼,只要裡面含有shared_ptr就有可能出問題 如果自己約束share的記憶體不含指標的話確實也能避免這問題 但我沒試過就是了 我之所以會裝物件是為了讓物件之間的聯繫能更安全 只要抓著指標就一定能聯絡上目標物件 也不用去想聯絡對象已經被解構了該如何處理 ※ 編輯: eye5002003 (118.167.54.239 臺灣), 06/16/2019 10:58:03
loveme00835: 那首先就要問到, 為什麼你要連絡的對象會比你還早被 06/16 12:04
loveme00835: 解構? 是不是你在基本上就無法掌握控制每個物件的生 06/16 12:05
loveme00835: 命週期, 導致只能用最簡單的方法: 讓 shared_ptr 幫 06/16 12:06
loveme00835: 你處理這些複雜事? 06/16 12:06
loveme00835: 一般分享物件都是用指標/參考, 為什麼你要用智慧指標 06/16 12:12
loveme00835: ? 這就是需要先討論的, 而不是先決定用智慧指標, 才 06/16 12:13
loveme00835: 來解決設計不良的問題 06/16 12:13
理想是配置記憶體能遵守stack先進後出原則 這樣當然每個參考對象使用時都會存在 但是實戰上你處理好的數據不見得一離開scope就肯乖乖釋放 也許預期到未來還有可能會用到 所以保留下來日後可以避免重算一次 另外像是有互動功能的程式 需要依使用者的操作來判斷什麼資源可以先釋放 (例如瀏覽器就無法預知你會先關掉哪個分頁) 沒辦法那麼理想的去固定解構順序 所以不是什麼設計不良造成的 而是真的就是需要 shared_ptr ※ 編輯: eye5002003 (118.167.54.239 臺灣), 06/16/2019 13:10:04
loveme00835: 那就是你在處理這些需要重用的資源時, 除了什麼scope 06/16 14:23
loveme00835: 以外, 沒有想過其它的管理方式 06/16 14:24
loveme00835: 舉個例子, 如果資源是和 task 作關聯, 如果作完就要 06/16 16:23
loveme00835: 釋放, 那麼就可以讓 function object 來 own 資源, 06/16 16:23
loveme00835: 在 dispath task 的時候, 把資源 move 出去讓特定的 06/16 16:24
loveme00835: 物件去管理. 你可以嘗試把這種 own shared_ptr 的類 06/16 16:26
loveme00835: 別/物件都畫一條線出來, 你會發現這樣的圖會很複雜, 06/16 16:26
loveme00835: 所以在用智慧指標前, 你需要好好地思考是不是在不得 06/16 16:28
loveme00835: 不用的情況下才寫, 還是懶得設計為了方便才寫. 大部 06/16 16:29
loveme00835: 份情況都是 unique_ptr 就可以解掉的問題, 或許你可 06/16 16:30
loveme00835: 以說說你不得不用的理由? 通常就是招式用盡才會出 06/16 16:31
loveme00835: shared_ptr 06/16 16:31
KanzakiHAria: 一般軟工把這個現象稱為 "設計不良" 06/17 21:32
Killercat: 你的case可以參考一下是否該使用std::unique_ptr 06/18 11:15
Killercat: shared_ptr的確是有這種ownership(肇因於設計不良)不明 06/18 11:15
Killercat: 的case,這種其實把權責劃分一下滿容易解決的 06/18 11:16
Killercat: 很多人把shared_ptr當scope ptr在用 但是別忘了使用的 06/18 11:17
Killercat: 時候,總要記得這ptr總該要有個ownership的 06/18 11:17
Killercat: 像你預期未來會在用到 那你就該有個controller處理這個 06/18 11:18
Killercat: 真的決定要cleanup時的邏輯 ownership要歸給該control 06/18 11:18
Killercat: 請注意shared_ptr不是GC 不要老用GC觀點思考這問題 06/18 11:19
Killercat: 你很多思考上都是把它當GC了 這兩個是完全不同的概念 06/18 11:20
eye5002003: 確實unique_ptr才是謹慎的選擇 06/18 15:52
firejox: https://youtu.be/JfmTagWcqoE 06/21 21:44
這影片有回答到兩個我一開始提到的疑慮 1.module要分層級來管制指標方向(我當前的策略) 2.別丟shared_ptr進std::function,要丟weak_ptr shared_ptr用起來很方便 唯一要擔心的是它會串成一圈 最終還是只能自己注意管理 並節制使用,優先考慮使用unique_ptr ※ 編輯: eye5002003 (118.167.48.176 臺灣), 06/27/2019 08:17:37