A template class for smart reference-counting pointers
OpenCV 2.0では cv::Ptr という参照カウント方式のスマートポインタが用意されています。
これは Boost C++ Library の shared_ptr と同様のもので大変便利です。
参考:参照カウント – Wikipedia
一時的にcv::Ptrクラスのrefcountというメンバをprotectedからpublicに変更して挙動を見てみます。
(cxcore.hppの660行目付近にあります)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
class Test { public: Test() { std::cout<<"construct"<<std::endl; } ~Test() { std::cout<<"destruct"<<std::endl; } }; int main(void) { using namespace std; cv::Ptr<Test> p1(new Test()); // 参照カウント 1 cout<<"refcount: "<<*(p1.refcount)<<endl; { cv::Ptr<Test> p2; p2 = p1; // 参照カウントが+1されて2になる cout<<"refcount: "<<*(p1.refcount)<<endl; } // 参照カウントが-1されて1になる、まだオブジェクトは解放されない cout<<"refcount: "<<*(p1.refcount)<<endl; cout<<"main exit"<<endl; return 0; } // Testオブジェクトが解放される -------------- /** 結果 construct refcount: 1 refcount: 2 refcount: 1 main exit destruct **/ |
すばらしい。
また、IplImage に適用した場合はきちんとテンプレートの特殊化が施されているので安心です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
int main(void) { cv::Ptr<IplImage> img = cvLoadImage("test.jpg"); if(img.empty()) { std::cerr<<"can't load image."<<std::endl; return -1; } namedWindow("image", CV_WINDOW_AUTOSIZE); imshow("image", Mat(img)); waitKey(); return 0; } -------------------------------------------------------------------- /* 参照カウント(refcount)が0になると Ptr::delete_obj() が呼ばれる CvMatやIplImageは以下のように特殊化されている */ template<> inline void Ptr<CvMat>::delete_obj() { cvReleaseMat(&obj); } template<> inline void Ptr<IplImage>::delete_obj() { cvReleaseImage(&obj); } |
OpenCV 1.0ではメモリのアロケートに cvAlloc() という malloc() のラッパーが使われていましたが、
OpenCV 2.0ではその代わりに fastMalloc() という関数が用意され、cv::Ptr内でもコールされています。
少し中を覗いてみると、どうやらシステムコールの mmap() でアロケートしているようです。
(Windowsでは普通のmalloc()が呼ばれる模様)
詳しくはまだ読めていませんが、fastというくらいだからきっと速くなっているんでしょう。
メモリ管理を cv::Ptr に任せておくと開発が楽になるのは間違いなさそうです。
関連記事:
OpenCV 2.0を試してみた