【深度探索STL】空间配置器(四) 内存基本处理

来源:互联网 发布:office for mac 费用 编辑:程序博客网 时间:2024/05/17 22:56

前面分别学习了:

  1. 对象的构造和析构              :http://blog.csdn.net/wenqian1991/article/details/19545049
  2. 空间配置器之第一级配置器:http://blog.csdn.net/wenqian1991/article/details/19566499
  3. 空间配置器之第二级配置器:http://blog.csdn.net/wenqian1991/article/details/19605727

这里继续学习基于配置器之上的一些内存基本处理工具。主要剖析 SGI STL 源码(http ://www.sgi.com/tech/stl/download.html  v3.3)中的几个内存处理函数(由函数名可知,是对未初始化空间的初始化操作,即通过复制或赋值的方式初始化未初始化的空间):
uninitialized_copy(),uninitialized_copy_n(),uninitialized_fill(),uninitialized_fill_n()

先学习 uninitiated_copy()

//stl source code(v3.3)//defined in <stl_uninitialized.h>inline char* uninitialized_copy(const char* __first, const char* __last, char* __result) {memmove(__result, __first, __last - __first);return __result + (__last - __first);  //返回该连续区域的末尾}inline wchar_t*   // typedef unsigned short wchar_t;uninitialized_copy(const wchar_t* __first, const wchar_t* __last, wchar_t* __result){memmove(__result, __first, sizeof(wchar_t)* (__last - __first));return __result + (__last - __first);}
上面两个是对两种特化类型的处理,下面为泛化版本

template <class _InputIter, class _ForwardIter>inline _ForwardIteruninitialized_copy(_InputIter __first, _InputIter __last, _ForwardIter __result){   //根据数值型别决议出最佳效率的函数return __uninitialized_copy(__first, __last, __result, __VALUE_TYPE(__result));}template <class _InputIter, class _ForwardIter, class _Tp>inline _ForwardIter__uninitialized_copy(_InputIter __first, _InputIter __last, _ForwardIter __result, _Tp*){typedef typename __type_traits<_Tp>::is_POD_type _Is_POD;   //判断数值型别//在C++中,我们把传统的C风格的struct叫做POD(Plain Old Data)对象return __uninitialized_copy_aux(__first, __last, __result, _Is_POD());}//如果copy construction 和 operator = 等效(POD type),并且 destructor is trivial 的情况 template <class _InputIter, class _ForwardIter>inline _ForwardIter__uninitialized_copy_aux(_InputIter __first, _InputIter __last, _ForwardIter __result, __true_type){/*针对POD对象,其二进制内容是可以随便复制的*/return copy(__first, __last, __result);/*简化处理,详见<stl_algobase.h>inline _Tp* copy(const _Tp* __first, const _Tp* __last, _Tp* __result){    memmove(__result, __first, sizeof(_Tp) * (__last - __first));    return __result + (__last - __first);}*/}/*如果copy construction 和 operator = 不等效,就需要调用 construct() 构造 */template <class _InputIter, class _ForwardIter>_ForwardIter__uninitialized_copy_aux(_InputIter __first, _InputIter __last, _ForwardIter __result, __false_type){_ForwardIter __cur = __result;/*下面就是捕捉异常处理*/__STL_TRY{    //#define __STL_TRY  tryfor (; __first != __last; ++__first, ++__cur) //一个一个元素的构造,无法批量进行_Construct(&*__cur, *__first);   //每个对象都以其它对象为蓝本进行构造,使用的是 placement newreturn __cur;}/*commit or rollback:要么构造出所有必要元素,要么(当有任何一个 copy construct 失败时)不构造任何东西,保证所有对象都被析构*/__STL_UNWIND(_Destroy(__result, __cur));//#define __STL_UNMIND(action)  catch(...) { action; throw;}}
POD就是标量型别或传统的C struct 型别,POD 型别必然拥有 trivial ctor / dtor / copy / assignment 函数,因此我们可以对POD型别进行判断,从而决议出最有效率的初值填写手法

不难发现上面 uninitiated_copy() 后,返回的是指向 copy 后的区块末端。

uninitiated_copy_n() 则是向指定欲初始化空间初始化(复制)指定大小已初始化空间的指定值(有点拗口)。

template <class _InputIter, class _Size, class _ForwardIter>inline pair<_InputIter, _ForwardIter>uninitialized_copy_n(_InputIter __first, _Size __count, _ForwardIter __result){//最后一个形参判断迭代器 first 的类别return __uninitialized_copy_n(__first, __count, __result, __ITERATOR_CATEGORY(__first));}//函数返回两个值,采用 pair 对组//迭代器型别为支持随机存取的迭代器,涵盖所有指针运算能力,可以直接使用uninitialized_copy()进行复制template <class _RandomAccessIter, class _Size, class _ForwardIter>inline pair<_RandomAccessIter, _ForwardIter>__uninitialized_copy_n(_RandomAccessIter __first, _Size __count, _ForwardIter __result, random_access_iterator_tag){_RandomAccessIter __last = __first + __count;return pair<_RandomAccessIter, _ForwardIter>(__last, uninitialized_copy(__first, __last, __result));}//迭代器为只读型别,所指的对象不允许外界改变template <class _InputIter, class _Size, class _ForwardIter>pair<_InputIter, _ForwardIter>__uninitialized_copy_n(_InputIter __first, _Size __count, _ForwardIter __result, input_iterator_tag){/*针对输入范围内的每一个迭代器,函数会调用construct()函数产生迭代器所指对象的复制品,放置于输出范围的相应位置上*/_ForwardIter __cur = __result;__STL_TRY{        for (; __count > 0; --__count, ++__first, ++__cur)_Construct(&*__cur, *__first);return pair<_InputIter, _ForwardIter>(__first, __cur);}__STL_UNWIND(_Destroy(__result, __cur));}
上面函数都是返回 pair 对组类型。其实就是返回两个值,一个是 “只读” 型别的迭代器(_InputIter),一个是允许 “写入型” 的迭代器(_ForwardIter)。
下面这个函数 uninitiated_fill() 和 uninitiated_copy() 操作很像,只不过前者是赋值,后者是复制。

//迭代器类型为“写入型”。该函数的功能就是给迭代器指定范围内赋值//具体实现过程参考函数 uninitialized_copy()template <class _ForwardIter, class _Tp>inline void uninitialized_fill(_ForwardIter __first, _ForwardIter __last, const _Tp& __x){__uninitialized_fill(__first, __last, __x, __VALUE_TYPE(__first));}//判断数值型别,同 uninitialized_copy()template <class _ForwardIter, class _Tp, class _Tp1>inline void __uninitialized_fill(_ForwardIter __first, _ForwardIter __last, const _Tp& __x, _Tp1*){typedef typename __type_traits<_Tp1>::is_POD_type _Is_POD;__uninitialized_fill_aux(__first, __last, __x, _Is_POD());}template <class _ForwardIter, class _Tp>inline void__uninitialized_fill_aux(_ForwardIter __first, _ForwardIter __last, const _Tp& __x, __true_type){fill(__first, __last, __x);/*简化处理,参见<stl_algobase.h>template <class _ForwardIter, class _Tp>void fill(_ForwardIter __first, _ForwardIter __last, const _Tp& __value) {for ( ; __first != __last; ++__first)*__first = __value;}*/}template <class _ForwardIter, class _Tp>void__uninitialized_fill_aux(_ForwardIter __first, _ForwardIter __last, const _Tp& __x, __false_type){_ForwardIter __cur = __first;__STL_TRY{for (; __cur != __last; ++__cur)_Construct(&*__cur, __x);}__STL_UNWIND(_Destroy(__first, __cur));}
下面的函数 uninitiated_fill_n() 则是向指定欲初始化空间初始化(赋值)指定大小空间的指定值。

template <class _ForwardIter, class _Size, class _Tp>inline _ForwardIteruninitialized_fill_n(_ForwardIter __first, _Size __n, const _Tp& __x){return __uninitialized_fill_n(__first, __n, __x, __VALUE_TYPE(__first));}template <class _ForwardIter, class _Size, class _Tp, class _Tp1>inline _ForwardIter__uninitialized_fill_n(_ForwardIter __first, _Size __n, const _Tp& __x, _Tp1*){typedef typename __type_traits<_Tp1>::is_POD_type _Is_POD;return __uninitialized_fill_n_aux(__first, __n, __x, _Is_POD());}template <class _ForwardIter, class _Size, class _Tp>_ForwardIter__uninitialized_fill_n_aux(_ForwardIter __first, _Size __n, const _Tp& __x, __false_type){_ForwardIter __cur = __first;__STL_TRY{for (; __n > 0; --__n, ++__cur)_Construct(&*__cur, __x);return __cur;}__STL_UNWIND(_Destroy(__first, __cur));}template <class _ForwardIter, class _Size, class _Tp>inline _ForwardIter__uninitialized_fill_n_aux(_ForwardIter __first, _Size __n, const _Tp& __x, __true_type){return fill_n(__first, __n, __x);/*简化处理,参见<stl_algobase.h>template <class _OutputIter, class _Size, class _Tp>    _OutputIter fill_n(_OutputIter __first, _Size __n, const _Tp& __value){for ( ; __n > 0; --__n, ++__first)*__first = __value;return __first;}*/}
STL 定义的这几个全局函数(包括前面介绍的用于构造的 construct() 和 用于析构的 destroy()),作用于未初始化空间上,这样的功能对于容器的实现很有帮助。

参考资料:《STL 源码剖析》

0 0