문제
OpenCV 라이브러리와 함께 C ++를 사용하고 있습니다.이 질문은이 질문과 관련이 없지만 라이브러리 이미지 처리입니다. 현재 나는 디자인 결정을 내 렸습니다.
C 라이브러리 인 OpenCV에는 데이터 구조 (예 : CVMAT)가 스트러크로 선언된다. 그것들을 만들려면 cvcreatemat와 같은 함수를 사용하고 해제하려면 cvreleasemat와 같은 함수를 사용합니다. C ++ 프로그래머이기 때문에 나는 특별한 cv_scoped
CVReleAsemat가 자동으로 범위를 벗어 났을 때 자동으로 호출하는 클래스 boost::scoped_ptr
).
내가 지금 깨닫는 것은 내가 사용할 수 있기를 바랍니다. auto_ptr
그리고 shared_ptr
경우에도. 나는 단지 내 자신의 글쓰기 코드를 느낍니다 cv_auto_ptr
그리고 cv_shared_ptr
수업은 시간 낭비는 말할 것도없이 나쁜 생각이 될 것입니다. 그래서 저는 솔루션을 찾고 있었고 세 가지 가능성을 생각해 냈습니다.
첫 번째, 나는 이미 만든 CV_SCOPED 클래스를 사용할 수 있습니다. 나는 그것을 이름으로 바꿀 것입니다 cv_ptr
그런 다음 STAL과 같은 스마트 포인터를 사용하십시오. 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 용으로 설계되었습니다. 구조물/파괴자는 여기에 사용하지 말아야 할 것 (그러나 할 수있는)으로 여기에 사용하는 것입니다.
어쨌든 매번 동적으로 할당하지 않고 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() );
// . . .
}
Deleter는 공유 포인터에 매장이므로 공유 원시 포인터를 최종적으로 삭제해야 할 때만 사용할 수 있습니다. 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"의 Hodge Podge를 사용하는 것은 두통의 레시피와 불필요한 합병증처럼 들립니다.