[转]http://hi.baidu.com/maxint/blog/item/fc817c2f29881f331e3089ef.html
1. 安全指针
从opencv2.0开始,很多C数据结构变成了C++的类,考虑到兼容性,保留旧的API。在内存管理方面,提供安全指针类Ptr,让在此以前旧的需要手动管理内存的数据结构(IplImage, CvMat等)无需手动Release,用法为:
Ptr<IplImage> img = cvReadImage("Lena.jpg");
Ptr是一个模板类,在opencv中定义如下:
template<typename _Tp> class Ptr { public: Ptr(); Ptr(_Tp* _obj); ~Ptr(); Ptr(const Ptr& ptr); Ptr& operator = (const Ptr& ptr); void addref(); void release(); void delete_obj(); bool empty() const; _Tp* operator -> (); const _Tp* operator -> () const; operator _Tp* (); operator const _Tp*() const; protected: _Tp* obj; int* refcount; };
上述源码定义在原有的指针类加了个指针引用数(refcount),对一些操作符进行了重载(operator ->;())。值得注意的是,Ptr template 对指针指向的对象有一个要求,就是可以用 delete 操作土符来释放内存。你可能就想到 IplImage 就不满足这个要求了,这怎么办?可以使用模板特化(template specialization)重载 Ptr<Iplimage>::delete_obj() 函数:
template<> inline void Ptr<IplImage>::delete_obj()
{ cvReleaseImage(&obj); }
2. 指针对齐(http://bytes.com/topic/c/answers/213142-what-pointer-alignment)
为什么要指针对齐? 这是因为在某些架构上,只有能被指定数(如4,16)整除的内存地址才能够被访问,否则程序会crash,或者出现错误的结果,或者数据的访问变慢。举个例子来说,很多系统都要求interger的地址从偶数开始。opencv2.0以上版本很多指针都是被对齐过的,使指针地址能够被16整除。opencv中的内存一般是通过malloc分配,不能保证都是都能被16整除,此时需要截断,但是剩下的内存要如何维护? CV2.0的这样维护的:在 malloc 是多申请一个指针的空间,这个指针指向 malloc 得到的真实内存地址,只在 free 时使用它。相关函数:
typedef unsigned char uchar; #define CV_MALLOC_ALIGN 16 template<typename _Tp> static inline _Tp* alignPtr(_Tp* ptr, int n=(int)sizeof(_Tp)) { return (_Tp*)(((size_t)ptr + n-1) & -n); } __declspec(dllexport) void* fastMalloc( size_t size ) { uchar* udata = (uchar*)malloc(size + sizeof(void*) + CV_MALLOC_ALIGN); //HERE 多申请一个 void* 的空间用于存储 udata uchar** adata = alignPtr((uchar**)udata + 1, CV_MALLOC_ALIGN); adata[-1] = udata; //<- 存储 udata return adata; } __declspec(dllexport) void fastFree(void* ptr) { if(ptr) { uchar* udata = ((uchar**)ptr)[-1]; assert(udata < (uchar*)ptr && ((uchar*)ptr - udata) <= (ptrdiff_t)(sizeof(void*)+CV_MALLOC_ALIGN)); free(udata); } }