在過去的幾周裏,我一遍又一遍地遇到同樣的問題。歸結於它的核心,我建的對象像(向無環)層次:複合模式下的內存管理
a -> c
b -> c
b -> d
一個實例可以有一個以上的父母,更比一個孩子。 c
可能是讀者和作者共享的價值。 b
可能是一個複合值。層級很容易由工廠創建 - 例如a.setChild(new C())
。後來,客戶只關心根,她稱之爲getValue()
或setValue()
。
我的問題是:誰清除了層次結構?誰負責b
或c
請致電delete
?
選項 - 工廠創建的節點,工廠必須刪除節點: 我不喜歡這樣的選擇,因爲我明白一個工廠爲
new
的替代品。保持工廠感覺很奇怪,直到它創建的實例可能被銷燬。選項 - 「智能」指針: 少得多好,因爲它污染的接口,並介紹了一個簡單的事情,有很多複雜的如指針。
選項 - 任何內存管理的曲線狀類: 類收集所有節點
a
,b
,c
,d
,......並提供訪問根。節點本身互相引用,但不要刪除孩子或父母。如果「圖形」或複合管理器被銷燬,它會銷燬所有節點。
我更喜歡最後一個選項。但是,它使層次結構的構建複雜化。您可以在外部構建層次結構,並將圖表告訴每個節點,也可以在圖形內部構建層次結構,這種結構聞起來像選項1.該圖只能刪除,它知道的內容。因此,如果必須將節點傳遞給圖形,設計中會出現內存泄漏。
是否有這種問題的模式?你更喜歡哪種策略?
編輯1 - 2014年9月1日:對不起,針對智能指針不明確。我試圖避免另一個「何時使用智能指針問題」,而是將問題集中在替代解決方案上。但是,如果它們確實是最好的選擇(或者必要時),我願意使用智能指針。
在我看來,簽名setChild(C* child)
應該優於setChild(std::shared_ptr<C> child)
,原因相同 - 每個循環都應該優於迭代器。但是,我必須承認,像std:string
一樣,共享指針對其語義更具體。
就複雜性而言,現在節點內的每個操作都必須處理共享指針。 std::vector<C*>
變爲std::vector< std::shared_ptr<C> >
,...此外,每個指針都帶有一個引用計數,如果有其他選項,則可以避免這種引用計數。
我應該補充說我開發了一個實時系統的低層部分。它不是固件,但很接近。
編輯2-9月1st,2014: 謝謝你的所有輸入。我的具體問題是:我得到一個可以說傳感器數據的字節數組。在某個時刻,我被告知哪個值寫在該陣列的哪個位置。一方面,我想要從數組中的某個位置映射到原始值(int32,double,...)。另一方面,我想將原始值合併到複雜類型(結構,向量,...)中。不幸的是,並非所有的映射都是雙向的。例如。我可以讀取值之間的比較,但不能根據比較結果寫入值。因此,我將讀者和作者分開,並在必要時讓他們獲得相同的價值。
爲什麼智能指針會污染接口並引入複雜性? – 2014-09-01 13:23:22
「它污染了界面」舉個例子。 – 2014-09-01 13:31:37
如果「客戶只關心根」,那麼智能指針不會暴露在界面中,不管您是否認爲這種暴露是「污染」。或者你指的是構建圖形的界面?在這種情況下,我認爲智能指針與污染完全相反,因爲它們明確指定了所有權模型。 – 2014-09-01 13:49:47