智能指针与C语言编写的一个库
-
20-08-2019 - |
题
我使用C ++与OpenCV库,这是一个库图像处理虽然这不是相关的这个问题。目前,我有一个设计决定。
OpenCV的,是一个C库,有其数据结构(如与CvMat)声明为结构。要创建它们,您使用功能,如cvCreateMat,并释放他们,您使用功能,如cvReleaseMat。作为一个C ++程序员,我创建了一个特殊的cv_scoped
类会自动调用cvReleaseMat当它走出范围(如boost::scoped_ptr
)。
什么我现在意识到的是,我希望我可以用auto_ptr
和shared_ptr
的情况下也是如此。我只是觉得,我自己cv_auto_ptr
和cv_shared_ptr
类编写代码将是一个糟糕的主意,更何况是浪费时间。所以,我一直在寻找的解决方案,我想出了三种可能性。
首页后,我可以用我已经取得了cv_scoped类。我想它重新命名为cv_ptr
,然后使用智能指针像这样:std::auto_ptr<cv_ptr>
。这个虽然讨厌的事情是,我总是不得不取消引用两次:
std::auto_ptr<cv_ptr> matrix(cv_ptr(cvCreateMat(320, 240, CV_32FC3)));
cvPow(matrix.get()->get()); // one get for the auto_ptr, one for the cv_ptr
我知道它看起来像我可以申报隐式转换,但我不能真正 - 大多数的OpenCV的函数具有参数无效* - 因此没有隐式转换将被调用。我真的想这样做的方式,我没有做双解引用。
<强>第二下,我可以以某种方式覆盖operator delete
。我不想覆盖全球运营删除,因为我只希望这适用于CvMat中(和其他一些)类型。但是,我不能改变图书馆,所以我不能添加operator delete
的结构与CvMat。所以,我不知道如何做到这一点的工作。
第三,我可以只重写我自己auto_ptr
,scoped_ptr
和shared_ptr
。他们不是大班这样就不会太困难,但我只是觉得这是不好的设计。如果我这样做,我可能会做沿着这些路线的东西:
class cv_auto_ptr {
public:
cv_auto_ptr();
~cv_auto_ptr();
// each method would just be a proxy for the smart pointer
CvMat* get() { return this->matrix_.get()->get(); }
// all the other operators/methods in auto_ptr would be the same, you get the idea
private:
auto_ptr<cv_ptr> matrix_; // cv_ptr deletes CvMat properly
}
你会在我的情况怎么办?请帮助我这一个。
解决方案
auto_ptr的真正设计用于C ++类RAII与构造/析构函数你在这里推动它们的用途他们可能不应该使用的东西(但可以)。
反正don'y要能够使用C ++对象,就好像它是一个正常的堆栈变量而不必每次动态分配
在标准解决问题的方法是创建具有构造/析构的包装。结果 但是,使其可用由C功能只需添加一个内部转换运算符,因此自动神奇地传递给C函数时转换本身回C对象
写包装类。
class Mat
{
CvMat* impl;
public:
Mat(/* Constructor Arguments */)
{
impl = cvCreateMat(/* BLAH */);
}
~Mat()
{
cvReleaseMat(impl);
}
operator CvMat*()
{ // Cast opertator. Convert your C++ wrapper object into C object
// when you use it with all those C functions that come with the
// library.
return impl;
}
};
void Plop(CvMat* x)
{ // Some C function dealing with CvMat
}
int main()
{ // Don't need to dynamically allocate
Mat m; // Just create on the stack.
Plop(m); // Call Plop directly
std::auto_ptr<Mat> mP(new Mat);
Plop(*mP);
}
其他提示
这是可以考虑的一种方法是使用的std::tr1::shared_ptr
具有功能,以提供一个定制删除的事实。我有OpenCV的,所以我从你写的推断不熟悉。
struct CvMatDeleter
{
void operator( CvMat* p ) { cvReleaseMat( p ) ; }
};
void test()
{
std::tr1::shared_ptr< CvMat > pMat( cvCreateMat(320, 240, CV_32FC3), CvMatDeleter() );
// . . .
}
由于所述删除器是存储在共享指针可以只使用它作为正常并且当所述共享原始指针最后需要被删除,cvReleaseMat
将根据需要调用。需要注意的是auto_ptr
和scoped_ptr
轻得多类,所以不具备自定义删除器的功能,但如果你在小的开销准备再shared_ptr
可以在他们的地方使用。
如果你关心的是异常安全,做到这一点,每次使用矩阵:
void f() {
try {
CvMat* mat = cvCreateMat(320, 240, CV_32FC3));
// ...
} catch(...) {
cvReleaseMat(mat);
throw;
}
cvReleaseMat(mat);
}
如果,在另一方面,你想有一个健全解决方案,多走一英里,写一个完整的包装。
namespace cv {
class Mat {
public:
enum Type { /* ... */ };
Mat(int w, int h, Type type) {
impl = cvCreateMat(w, h, intFromType(type));
}
~Mat() {
cvReleaseMat(impl);
}
void pow() { // wrap all operations
cvPow(impl);
}
private:
CvMat* impl;
};
}
去的中间道路,使用通用智能指针的霍奇波奇和“cv_ptrs”听起来像头痛配方和不必要的复杂性。