【发布时间】:2011-03-22 08:25:33
【问题描述】:
考虑以下类结构:
class Filter
{
virtual void filter() = 0;
virtual ~Filter() { }
};
class FilterChain : public Filter
{
FilterChain(collection<Filter*> filters)
{
// copies "filters" to some internal list
// (the pointers are copied, not the filters themselves)
}
~FilterChain()
{
// What do I do here?
}
void filter()
{
// execute filters in sequence
}
};
我在库中公开这个类,所以我无法控制它的使用方式。
我目前有一些关于Filter 对象所有权的设计问题FilterChain 持有指向的指针。更具体地说,这里是FilterChain 的两种可能的使用场景:
- 场景 A:我的库中的一些函数正在构建一个(可能很复杂)过滤器链,根据需要分配内存,并返回一个新分配的
FilterChain对象。例如,其中一个函数从一个文件构造一个过滤器链,可以描述任意复杂的过滤器(包括过滤器链的过滤器链等)。工作完成后,函数的用户负责对象销毁。 - 场景 B:用户可以访问一堆
Filter对象,并希望以特定方式将它们组合到过滤器链中。用户构造FilterChain对象供自己使用,然后在完成后销毁它们。当引用它们的FilterChain被销毁时,Filter对象不得被销毁。
现在,在FilterChain 对象中管理所有权的两种最简单方法是:
-
FilterChain拥有Filter对象。这意味着FilterChain引用的对象在FilterChain的析构函数中被销毁。这与场景 B 不兼容。 -
FilterChain不拥有Filter对象。这意味着FilterChain的析构函数什么都不做。现在方案 A 存在问题,因为用户必须知道所涉及的所有Filter对象的内部结构才能将它们全部销毁而不会丢失任何一个,因为父FilterChain自己不会这样做。这只是糟糕的设计,并要求内存泄漏。
因此,我需要一些更复杂的东西。我的第一个猜测是设计一个带有可设置布尔标志的智能指针,指示智能指针是否拥有该对象。然后,FilterChain 将不采用指向 Filter 对象的指针集合,而是采用指向 Filter 对象的智能指针集合。当FilterChain 的析构函数被调用时,它会破坏智能指针。然后,智能指针本身的析构函数将销毁指向的对象(Filter 对象)当且仅当设置了指示所有权的布尔标志。
我觉得这个问题在 C++ 中很常见,但是我在网上搜索流行的解决方案或聪明的设计模式并不是很成功。事实上,auto_ptr 在这里并没有真正的帮助,shared_ptr 似乎有点矫枉过正。那么,我的解决方案是不是一个好主意?
【问题讨论】:
-
为什么共享指针是多余的?在立即实施和维护方面比自己动手要容易得多(每个人都知道它们是什么)。开销很小。
-
基类析构函数必须是虚拟的。
-
@Patrick:对我来说感觉有点矫枉过正,因为 shared_ptr 是一个引用计数器,我只需要一个布尔标志。
-
@Neil Butterworth:是的,当然。为了简洁起见,我省略了它。
-
但是编写和测试一个完整的智能指针类不是比使用一个使用 int 而不是 bool 的预测试类更过分吗?也有理由认为 std::shared_ptr 实现会比我第一次尝试智能指针类更好(代码大小、速度等)......
标签: c++ memory-management pointers ownership