【问题标题】:common way to encapsulate C-type pointers with custom deleters使用自定义删除器封装 C 类型指针的常用方法
【发布时间】: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_ptr here 的 Boost 文档中,他们建议在这种情况下使用 weak_ptr(如果我理解正确的话)。

标签: c++ c shared-ptr


【解决方案1】:

包装器似乎是一个不错的方法。如果您为 C++ 类定义析构函数,那么它可以为您释放内存。当你的类超出范围时,析构函数会被自动调用,所以这应该会给你你所追求的想法。如果在内存清理过程中有用,您还可以在析构函数中实现对 NUL ptr 或悬空 ptr 的检查。

class IplImageObj {
    IplImage* ptr;
    ~IplImageObj(){ /* The destructor: you can call cvReleaseImage from here  */}
public:
    IplImageObj(IplImage* img): ptr(img){}
    // ...
};

在上面的 sn-p 中,数据成员 ptr 是私有的,因此您可能需要访问器函数才能对其进行任何操作。

我的 C++ 讲师强烈反对 publicclass 中声明数据成员。如果你想让数据成员公开,那么struct拥有现在class的所有功能,人们对数据成员的公开访问更加宽容……

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-05-28
    • 1970-01-01
    • 2021-06-05
    • 2022-06-23
    • 1970-01-01
    • 1970-01-01
    • 2011-09-14
    相关资源
    最近更新 更多