STL源码剖析(二):空间配置器allocator(3)

空间配置讲完了,那如何在分配的空间上进行数据操作呢?前面讲过了construct()和destroy(),另外还有三个填充类函数,其实际定义于<stl_uninitialized>:

一、uninitialized_copy:区间拷贝

// 内存的配置与对象的构造行为分离开来。
template <class _InputIter, class _ForwardIter>
inline _ForwardIter
  uninitialized_copy(_InputIter __first, _InputIter __last,
                     _ForwardIter __result)
{
  return __uninitialized_copy(__first, __last, __result,
                              __VALUE_TYPE(__result));
}

简单来说就是首先得到__result的 value_type(如是是否POD类型,判断是否含有non-trivial 函数),进而判断是调用construct() 还是 直接调用memmove()或copy() ;然后,就是把 [__first,__last)这个区间上的数据,挨个复制到目标容器上。

可以看出__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;
  return __uninitialized_copy_aux(__first, __last, __result, _Is_POD());
}

// 如果是trival construct,直接内存拷贝
template <class _InputIter, class _ForwardIter>
inline _ForwardIter 
__uninitialized_copy_aux(_InputIter __first, _InputIter __last,
                         _ForwardIter __result,
                         __true_type)
{
  return copy(__first, __last, __result);
}

// 如果是non-trival construct,挨个复制
template <class _InputIter, class _ForwardIter>
_ForwardIter 
__uninitialized_copy_aux(_InputIter __first, _InputIter __last,
                         _ForwardIter __result,
                         __false_type)
{
  _ForwardIter __cur = __result;
  __STL_TRY {
    for ( ; __first != __last; ++__first, ++__cur)
      _Construct(&*__cur, *__first);
    return __cur;
  }
  __STL_UNWIND(_Destroy(__result, __cur));
}

针对char* 和 wchar_t* 两种类型,用memmove(直接移动内存内容)来执行复制行为,以下是两种类型的特化版本:

inline char* uninitialized_copy(const char* __first, const char* __last,
                                char* __result) {
  memmove(__result, __first, __last - __first);
  return __result + (__last - __first);
}

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);
}

二、uninitialized_fill:区间单值填充

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

可以看出,就是将__x的值复制到[__first,__last),复制的技法和uninitialized_copy类似。注意这里的__first和__last是目标迭代器。

三、uninitialized_fill_n

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));
}

和上一个函数很相近,只不过是把区间终点换成区间长度了。

总结:以上三个函数,其实就是结合转调实现泛化和特化的一个过程。

个人感觉:char* 类型的特化,有点像打补丁,应该归属 __true_type那个版本中去,然后再特化,不调用copy()而调用memmove(),这样更好理解一些。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值