STL源码剖析--内存基本处理工具

内存基本处理工具

STL定义有5个全局函数,除了前面的construct(),destory(),还有uninitialized_copy()、uninitialized_fill()、uninitialized_fill_n()函数,它们三个分别应用于STL中高层次函数:copy()、fill()、fill_n()

uninitialized_copy

template <class _InputIter, class _ForwardIter>
inline _ForwardIter
  uninitialized_copy(_InputIter __first, _InputIter __last,
                     _ForwardIter __result);

uninitialized_copy()可以将内存的配置与对象的构造行为分离开,作为输出目的地的[result,result+(last-first)]范围内的迭代器指向未初始化的区域,uninitialized_copy()会使用copy constructor,将输入来源的[first,last]范围内每一个对象的复制品放到输出范围中。

如果我们需要实现一个容器,那么这样的函数会对我们很有帮助。因为容器的全区间构造通常需要两个步骤完成:
* 配置内存区块,足以包含范围内的所有元素。
* 使用uninitialized_copy(),在内存区块上构造函数。

我们来看看uninitialized_copy()的在SGI中的详细实现:

/**
 * Name:uninitialized_copy
 * Args:1.first,指向输入端的起始位置的迭代器。
 *      2.last,指向输入端的结束位置的迭代器。
 *      3.result,指向输入端(欲初始化空间)的起始处。
 */
template <class _InputIter, class _ForwardIter>
inline _ForwardIter
  uninitialized_copy(_InputIter __first, _InputIter __last,
                     _ForwardIter __result)
{
  return __uninitialized_copy(__first, __last, __result,
                              __VALUE_TYPE(__result));
}
//首先利用_VALUE_TYPE()萃取出__result的类型,然后返回函数__uninitialized_copy(),那么__uninitialized_copy()又是怎么实现的?
/**
 * Name:__uninitialized_copy
 * Args:1.first,指向输入端的起始位置的迭代器。
 *      2.last,指向输入端的结束位置的迭代器。
 *      3.result,指向输入端(欲初始化空间)的起始处。
 *      4.Tp*,已推断的类型
 */
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; //判断_Tp是否为POD型别
  return __uninitialized_copy_aux(__first, __last, __result, _Is_POD());
}
//该函数为判断第四个参数的类型是否为POD型别,然后根据_Is_POD的返回值选择重载的函数__uninitialized_copy_aux(),下面为__uninitialized_copy_aux()的实现。

参考:POD型别

template <class _InputIter, class _ForwardIter>
inline _ForwardIter 
__uninitialized_copy_aux(_InputIter __first, _InputIter __last,
                         _ForwardIter __result,
                         __true_type)   //如果_Is_POD返回值为true
{
  return copy(__first, __last, __result);   //调用copy()
}

template <class _InputIter, class _ForwardIter>
_ForwardIter 
__uninitialized_copy_aux(_InputIter __first, _InputIter __last,
                         _ForwardIter __result,
                         __false_type)  //如果_Is_POD返回值为false
{
  _ForwardIter __cur = __result;
  __STL_TRY {
    for ( ; __first != __last; ++__first, ++__cur)
      _Construct(&*__cur, *__first);    //一个一个元素进行构造,无法批量进行
    return __cur;
  }
  __STL_UNWIND(_Destroy(__result, __cur));
}

对于char*wchar*两种类型,SGI分别设计了两种特化版本,是直接采用最具效率的memmove(直接移动内存内容)来执行复制行为:

//针对char*的特化版本
inline char* uninitialized_copy(const char* __first, const char* __last,
                                char* __result) {
  memmove(__result, __first, __last - __first);
  return __result + (__last - __first);
}
//针对wchar*的特化版本
inline 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);
}


stl_uninitialized.h文件中还定义了uninitialized_copy_n(),并不在C++标准库中,我们就不必研究了,有兴趣的可以去看看。

uninitialized_fill

template <class _ForwardIter, class _Tp>
inline void uninitialized_fill(_ForwardIter __first,
                               _ForwardIter __last, 
                               const _Tp& __x);

uninitialized_fill()也能够将内存配置与对象的构造行为分离开,如果[first,last]范围内的每个迭代器都指向未初始化的区域,那么uninitialized_fill()会在该范围内填充x的复制品。

我们来看uninitialized_fill()在SGI中的详细实现:

/**
 * Name:uninitialized_fill
 * Args:1.first,指向输出端的起始处的迭代器。
 *      2.last,指向输出端结束处的迭代器。
 *      3.x,需要设置的初值。
 */
template <class _ForwardIter, class _Tp>
inline void uninitialized_fill(_ForwardIter __first,
                               _ForwardIter __last, 
                               const _Tp& __x)
{
  __uninitialized_fill(__first, __last, __x, __VALUE_TYPE(__first));
}
//首先用__VALUE_TYPE()萃取__first的类型,然后传入__uninitialized_fill()中并返回该函数。下面为uninitialized_fill()的实现。
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;    //判断_Tp是否为POD型别
  __uninitialized_fill_aux(__first, __last, __x, _Is_POD()); 
}
//该函数判断传入的第四个参数的类型,然后根据根据_Is_POD返回值选择需要重载的函数。下面为__uninitialized_fill_aux()的实现。
template <class _ForwardIter, class _Tp>
inline void
__uninitialized_fill_aux(_ForwardIter __first, _ForwardIter __last, 
                         const _Tp& __x, __true_type)
{
  fill(__first, __last, __x);   //如果为POD类型,则调动STL中的fill()
}

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); //如果不为POD类型,则一个一个构造,无法批量进行
  }
  __STL_UNWIND(_Destroy(__first, __cur));
}

uninitialized_fill_n

template <class _ForwardIter, class _Size, class _Tp>
inline _ForwardIter 
uninitialized_fill_n(_ForwardIter __first, _Size __n, const _Tp& __x);

uninitialized_fill_n()也能使我们将内存配置与对象构造行为分离开,它会为指定范围内的所有元素设定相同的初值。

如果[first,last]范围内的每一个迭代器都指向未初始化的区域,那么uninitialized_fill_n()会调用copy constructor,在该范围内产生x的复制品。

uninitialized_fill_n()在SGI中的详细实现:

/**
 * Name:uninitialized_fill_n
 * Args:1.first,指向输出端的起始处的迭代器。
 *      2.last,指向输出端结束处的迭代器。
 *      3.x,需要设置的初值。
 */
template <class _ForwardIter, class _Size, class _Tp>
inline _ForwardIter 
uninitialized_fill_n(_ForwardIter __first, _Size __n, const _Tp& __x)
{
  return __uninitialized_fill_n(__first, __n, __x, __VALUE_TYPE(__first));
}
//首先用__VALUE_TYPE()萃取__first的类型,然后传入__uninitialized_fill_n()并返回该函数。下面为__uninitialized_fill_n()的实现。
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;    //判断是否为POD类型
  return __uninitialized_fill_n_aux(__first, __n, __x, _Is_POD());
}
//根据传入的第四个参数的类型是否为POD类型进行__uninitialized_fill_n()的重载。下面为__uninitialized_fill_n_aux()的实现。
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);     //如果为POD类型,则调用STL中的fill_n函数。
}

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);     //如果不是POD类型,则一个一个进行构造,无法进行批量处理。
    return __cur;
  }
  __STL_UNWIND(_Destroy(__first, __cur));
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值