【发布时间】:2013-11-29 10:57:32
【问题描述】:
几乎所有来自 C 库的 C 类型对象都有一些自定义删除器,例如OpenCV 中的IplImage* 具有cvReleaseImage(IplImage**) 删除功能。在 C++ 中,我希望我的代码始终确保最终删除每个对象。
我想以某种方式使用std::shared_ptr 及其自定义删除器功能最有意义。
一个示例/也许可能的解决方案是在this question 中,我将只使用shared_ptr<IplImage>,但使用default_delete<IplImage> 的专用版本。但是请参阅那里有关缺点的答案:C++ 标准不能保证shared_ptr 将使用default_delete 作为默认删除器,并且我不允许像我希望的那样专门化default_delete(请参阅here) .
另一种解决方案是这样的:
shared_ptr<IplImage> makeIplImage(IplImage* ptr) {
return shared_ptr<IplImage>(ptr, default_delete<IplImage>()); // using my specialised default_delete
}
但是当我想包装我的IplImage* 时,我必须小心不要忘记打电话给makeIplImage。
另一个解决方案是编写我自己的包装对象类,例如
class IplImageObj {
shared_ptr<IplImage> ptr;
public:
IplImageObj(IplImage* img) : ptr(img, default_delete<IplImage>()) {} // again using my specialised default_delete
// ...
};
我还没有真正在野外看到过这么多这样的解决方案。使用它们是一个坏主意吗?如果是这样,那么我想我错过了一些东西,但是什么?或者最常见/最有意义的方式是什么?
【问题讨论】:
-
我不知道什么是最常见的,但我会说使用包装器。因为如果您需要封装分配/删除,您可能还想封装其他内容。将整个 C 库的使用封装在这样一个类中可能是明智的。
-
你可以很容易地适应
boost::intrusive_ptr,或者你应该编写自己的smart_ptr。我会去编写 ptr 处理程序,所有标准或增强实现都缺乏功能。我在它们中看到的最大缺陷是您无法将处理类与其持有的指针相关联以检测挂起的引用。 -
@Raxvan:感谢您的建议。我认为
instrusive_ptr只有在已经存在一些引用计数的情况下才有意义,但在大多数情况下(也适用于IplImage),没有。关于关联:在关于shared_ptrhere 的 Boost 文档中,他们建议在这种情况下使用weak_ptr(如果我理解正确的话)。
标签: c++ c shared-ptr