【问题标题】:Memory management in the composite pattern复合模式中的内存管理
【发布时间】:2014-09-01 13:14:21
【问题描述】:

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

  • 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),原因与 for-each 循环应该优先于迭代器相同。但是,我必须承认,像 std:string 一样,共享指针的语义更具体。

就复杂性而言,节点内的每个操作现在都必须处理共享指针。 std::vector<C*> 变为 std::vector< std::shared_ptr<C> >, ... 此外,每个指针都携带一个引用计数,如果有其他选择,则可以避免这种情况。

我应该补充一点,我开发了一个实时系统的低级部分。它不是固件,而是关闭。

编辑 2 - 2014 年 9 月 1 日: 感谢您的所有意见。我的具体问题是:我得到一个字节数组,可以说传感器数据。在某些时候,我被告知哪个值被写入该数组的哪个位置。一方面,我想要从数组中的某个位置映射到原始值(int32,double,...)。另一方面,我想将原始值合并到复杂类型(结构、向量等)。不幸的是,并非所有映射都是双向的。例如。我可以读取值之间的比较,但我无法根据比较结果写入值。因此,我将读取器和写入器分开,并让他们在必要时访问相同的值。

【问题讨论】:

  • 为什么智能指针会污染接口并引入复杂性??
  • "它污染了界面" 举个例子。
  • 如果“客户端只关心根”,那么无论您是否认为这种暴露是“污染”,智能指针都不会暴露在界面中。还是您指的是用于构建图形的界面?在这种情况下,我认为智能指针与污染完全相反,因为它们明确指定了所有权模型。
  • 如果父母应该拥有孩子,则不应首选 parent.setChild(C* child)。首选 shared_ptr 或 unique_ptr。
  • abcd 的生命周期是多少?他们是独立的吗?或者他们会同时死去?

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


【解决方案1】:

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

智能指针是带内存管理的指针,正是你所需要的。

您不必在界面中公开智能指针,只要对象在某处仍由智能指针拥有,您就可以从智能指针获取原始指针(请注意,尽管这不一定是最好的主意, 接口中的智能指针远非丑陋的东西)。

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

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

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

【讨论】:

  • 我会说std::stringconst char* 相比会污染接口并增加不必要的开销;)
  • @JarkkoL 我猜你也会认为c++c 相比会污染接口并增加不必要的开销:)
  • 视情况而定,是的。例如。当 const char* 足够时使用字符串代替。我为内存限制实时系统开发,我不能像 tictacs 那样丢掉性能和内存:)
  • @JarkkoL 好点!我忘了说代码确实是实时应用程序的关键部分。 Drax,这会改变智能指针的适用性,还是编译器应该担心这个? (恐怕我在这一点上支持 JarkkoL。)
  • 我不会称std::string为“污染”,但它确实使该接口完全无法在其他语言中使用,甚至无法使用其他 C++ 编译器编译的代码。所以有时需要克制。
猜你喜欢
  • 1970-01-01
  • 2013-01-10
  • 2016-01-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多