复合模式中的内存管理

时间:2014-09-01 13:14:22

标签: c++ memory-management graph factory composite

在过去的几周里,我一遍又一遍地遇到同样的问题。归结为它的核心,我构建了一个(有向非循环)对象层次结构,如:

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

实例可以有多个父级和多个子级。 c可能是读者和作者之间共享的价值。 b可能是复合值。层次结构很容易由工厂创建 - 例如a.setChild(new C())。之后,客户只关心她调用getValue()setValue()的根。

我的问题是:谁清理了层次结构?谁有责任在deleteb上致电c

  1. 选项 - 工厂创建了节点,工厂必须删除节点: 我不喜欢这个选项,因为我理解工厂是new的替代品。保持工厂直到它创建的实例可以被销毁是感觉很奇怪。

  2. 选项 - “智能”指针: 不太好,因为它污染了界面,并为诸如指针之类的简单事物引入了很多复杂性。

  3. 选项 - 执行内存管理的类似图形的类: 该类收集所有节点abcd,...并提供对根的访问权限。节点本身相互引用,但不删除子节点或父节点。如果销毁“图形”或复合管理器,它将销毁所有节点。

  4. 我更喜欢最后一个选项。然而,它使层次结构的构造复杂化。您可以在外部构建层次结构,并告诉图表每个节点,或者在图形内部构建层次结构,这类似于选项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 - 2014年9月1日: 感谢您的所有输入。我的具体问题是:我得到一个字节数组,让我们说传感器数据。在某些时候,我被告知哪个值写在该数组中的哪个位置。一方面,我想要从数组中的位置到原始值(int32,double,...)的映射。另一方面,我想将原始值合并到复杂类型(结构,向量,......)。不幸的是,并非所有映射都是双向的。例如。我可以读取值之间的比较,但我不能根据比较结果写入值。因此,我将读者和作者分开,并在必要时让他们访问相同的值。

1 个答案:

答案 0 :(得分:5)

  

选项 - “智能”指针:不太好,因为它污染了   界面,并为一个简单的事情引入了很多复杂性   作为指针。

智能指针是具有内存管理的指针,这正是您所需要的。

你没有被迫在你的界面中暴露智能指针,你可以从智能指针获得一个原始指针,只要该对象仍然由智能指针所拥有(注意这不一定是最好的想法虽然,界面中的智能指针远非丑陋的东西。)

实际上在您的界面中暴露原始指针会间接引入更多的污染和复杂性,因为您需要记录使用智能指针时明确的所有权和生命周期规则,这使得它们比“简单指针”更简单易用。 p>

此外,它很可能是“未来”的做事方式:因为c ++ 11/14智能指针是std::string的标准的一部分,你会说std::string <与const char*相比,em>污染界面并引入了很多复杂性?

如果您遇到性能问题,那么问题是:您的手工制作替代解决方案是否真的更具性能(需要进行测量),并且在开发功能和维护代码所需的开发时间方面是值得的?