2014-09-01 48 views
3

在過去的幾周裏,我一遍又一遍地遇到同樣的問題。歸結於它的核心,我建的對象像(向無環)層次:複合模式下的內存管理

  • a -> c
  • b -> c
  • b -> d

一個實例可以有一個以上的父母,更比一個孩子。 c可能是讀者和作者共享的價值。 b可能是一個複合值。層級很容易由工廠創建 - 例如a.setChild(new C())。後來,客戶只關心根,她稱之爲getValue()setValue()

我的問題是:誰清除了層次結構?誰負責bc請致電delete

  1. 選項 - 工廠創建的節點,工廠必須刪除節點: 我不喜歡這樣的選擇,因爲我明白一個工廠爲new的替代品。保持工廠感覺很奇怪,直到它創建的實例可能被銷燬。

  2. 選項 - 「智能」指針: 少得多好,因爲它污染的接口,並介紹了一個簡單的事情,有很多複雜的如指針。

  3. 選項 - 任何內存管理的曲線狀類: 類收集所有節點abcd,......並提供訪問根。節點本身互相引用,但不要刪除孩子或父母。如果「圖形」或複合管理器被銷燬,它會銷燬所有節點。

我更喜歡最後一個選項。但是,它使層次結構的構建複雜化。您可以在外部構建層次結構,並將圖表告訴每個節點,也可以在圖形內部構建層次結構,這種結構聞起來像選項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,...)。另一方面,我想將原始值合併到複雜類型(結構,向量,...)中。不幸的是,並非所有的映射都是雙向的。例如。我可以讀取值之間的比較,但不能根據比較結果寫入值。因此,我將讀者和作者分開,並在必要時讓他們獲得相同的價值。

+0

爲什麼智能指針會污染接口並引入複雜性? – 2014-09-01 13:23:22

+0

「它污染了界面」舉個例子。 – 2014-09-01 13:31:37

+3

如果「客戶只關心根」,那麼智能指針不會暴露在界面中,不管您是否認爲這種暴露是「污染」。或者你指的是構建圖形的界面?在這種情況下,我認爲智能指針與污染完全相反,因爲它們明確指定了所有權模型。 – 2014-09-01 13:49:47

回答

5

選項 - 「智能」指針:要少得多好,因爲它污染了 界面,並引入了大量的複雜的一個簡單的事情,例如 的指針。

智能指針是指針與內存管理,這正是你所需要的。

你不必在你的界面中暴露智能指針,只要對象仍然是某個智能指針所擁有的,你就可以從智能指針獲得一個原始指針(注意,這不一定是最好的想法但是,界面中的智能指針遠不是一件醜陋的事情)。

實際上,在您的界面中暴露原始指針間接引入了更多的污染和複雜性,因爲您需要記錄使用智能指針時明確的所有權和生命期規則,這使得它們比「簡單指針」更加簡單。

此外,它是最有可能做的事情的「未來的危機」的方式:由於C++ 11月14日智能指針都不亞於std::string標準的一部分,你會說std::string污染界面和介紹了很多的複雜性const char*相比?

如果您遇到性能問題,那麼問題是:您的手是否會製作出真正更高性能(需要測量)的替代解決方案,是否值得開發此功能所需的開發時間以及維護代碼?

+0

我會說'std :: string'污染了接口,並且增加了不必要的開銷(與const char *'相比)) – JarkkoL 2014-09-01 13:46:40

+0

@JarkkoL我想你也會認爲'C++'會污染接口並增加不必要的開銷':) – Drax 2014-09-01 13:51:43

+0

取決於具體情況,是的。例如。當使用字符串而不是const char *時就足夠了。我開發的內存約束實時系統,我不能像tictacs扔掉性能和內存:) – JarkkoL 2014-09-01 14:10:15