- /*!
- Automatically Allocated Buffer Class
- The class is used for temporary buffers in functions and methods.
- If a temporary buffer is usually small (a few K's of memory),
- but its size depends on the parameters, it makes sense to create a small
- fixed-size array on stack and use it if it's large enough. If the required buffer size
- is larger than the fixed size, another buffer of sufficient size is allocated dynamically
- and released after the processing. Therefore, in typical cases, when the buffer size is small,
- there is no overhead associated with malloc()/free().
- At the same time, there is no limit on the size of processed data.
- This is what AutoBuffer does. The template takes 2 parameters - type of the buffer elements and
- the number of stack-allocated elements. Here is how the class is used:
- \code
- void my_func(const cv::Mat& m)
- {
- cv::AutoBuffer<float, 1000> buf; // create automatic buffer containing 1000 floats
- buf.allocate(m.rows); // if m.rows <= 1000, the pre-allocated buffer is used,
- // otherwise the buffer of "m.rows" floats will be allocated
- // dynamically and deallocated in cv::AutoBuffer destructor
- ...
- }
- \endcode
- */
- template<typename _Tp, size_t fixed_size=4096/sizeof(_Tp)+8> class CV_EXPORTS AutoBuffer
- {
- public:
- typedef _Tp value_type;
- enum { buffer_padding = (int)((16 + sizeof(_Tp) - 1)/sizeof(_Tp)) };
- //! the default contructor
- AutoBuffer();
- //! constructor taking the real buffer size
- AutoBuffer(size_t _size);
- //! destructor. calls deallocate()
- ~AutoBuffer();
- //! allocates the new buffer of size _size. if the _size is small enough, stack-allocated buffer is used
- void allocate(size_t _size);
- //! deallocates the buffer if it was dynamically allocated
- void deallocate();
- //! returns pointer to the real buffer, stack-allocated or head-allocated
- operator _Tp* ();
- //! returns read-only pointer to the real buffer, stack-allocated or head-allocated
- operator const _Tp* () const;
- protected:
- //! pointer to the real buffer, can point to buf if the buffer is small enough
- _Tp* ptr;
- //! size of the real buffer
- size_t size;
- //! pre-allocated buffer
- _Tp buf[fixed_size+buffer_padding];
- };
仔细观察,这是一个模板类,模板参数有两个,第一个是类型,第二个带默认值,表示元素个数为4096/sizeof(_Tp)+8,当然还有一个枚举型成员,enum { buffer_padding = (int)((16 + sizeof(_Tp) - 1)/sizeof(_Tp)) };实际上这个成员的取值范围依赖于_Tp,所以范围在1~16之间,所以仅仅用于数组的padding吧,并不能存放元素...
ptr:内存块首地址,默认空间较小时,则ptr = buf
size:内存块可以存放的元素个数
源码:
- /// AutoBuffer
- template<typename _Tp, size_t fixed_size> inline AutoBuffer<_Tp, fixed_size>::AutoBuffer()
- {
- ptr = buf;
- size = fixed_size;
- }
- template<typename _Tp, size_t fixed_size> inline AutoBuffer<_Tp, fixed_size>::AutoBuffer(size_t _size)
- {
- ptr = buf;
- size = fixed_size;
- allocate(_size);
- }
- template<typename _Tp, size_t fixed_size> inline AutoBuffer<_Tp, fixed_size>::~AutoBuffer()
- { deallocate(); }
- template<typename _Tp, size_t fixed_size> inline void AutoBuffer<_Tp, fixed_size>::allocate(size_t _size)
- {
- if(_size <= size)
- return;
- deallocate();
- if(_size > fixed_size)
- {
- ptr = cv::allocate<_Tp>(_size);
- size = _size;
- }
- }
- template<typename _Tp, size_t fixed_size> inline void AutoBuffer<_Tp, fixed_size>::deallocate()
- {
- if( ptr != buf )
- {
- cv::deallocate<_Tp>(ptr, size);
- ptr = buf;
- size = fixed_size;
- }
- }
- template<typename _Tp, size_t fixed_size> inline AutoBuffer<_Tp, fixed_size>::operator _Tp* ()
- { return ptr; }
- template<typename _Tp, size_t fixed_size> inline AutoBuffer<_Tp, fixed_size>::operator const _Tp* () const
- { return ptr; }
看一下带参数的构造函数,调用了allocate,可以发现当_size<=size时,内存块够用,不需要做任何事情,否则调用deallocate释放内存块,deallocate中先判断ptr是否等于buf,当ptr=buf时,这是块静态数组,无需释放,同时在allocate和deallocate中调用了cv空间下的allocate和deallocate函数。
我们查看一下原型:
- template<typename _Tp> static inline _Tp* allocate(size_t n)
- {
- return new _Tp[n];
- }
- template<typename _Tp> static inline void deallocate(_Tp* ptr, size_t)
- {
- delete[] ptr;
- }
很简单的写法,没什么难度...
到此为止,AutoBuffer轻松实现了...
- AutoBuffer<int> x;
- x[0] = 1;
注意一下,有一个特殊的用法,我们可以使用[]运算符,这是为什么呢?原因是上面两个强制转换函数,返回的是一个首地址ptr,于是相当于访问ptr[]了...
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u012866104/article/details/50969539