内存基本处理工具

STL 定义五个全局函数,作用于未初始化空间上,分别是:construct(),destroy(),uninitialized_copy(),uninitialized_fill(),uninitialized_fill_n(),后三个函数 SGI 把它们定义于头文件 <stl_uninitialized> 分别对应于STL 函数copy(),fill(),fill_n() 。

uninitialized_copy

uninitialized_copy 使我们能够将内存的配置与对象的构建行为分离开。

如果作为输出目的范围的每一个迭代器指向一个未初始化的区域,uninitialized_copy 会使用 copy constructor,为身为输入源范围内的每一个对象产生一份复制品,放进输出范围中。

template <class _InputIter, class _Size, class _ForwardIter>
inline pair<_InputIter, _ForwardIter>
uninitialized_copy_n(_InputIter __first, _Size __count,
                     _ForwardIter __result) {
  return __uninitialized_copy_n(__first, __count, __result,
                                __ITERATOR_CATEGORY(__first));
}

容器的全范围构建内构建通常有两个步骤:

  • 配置内存区块,足以包含范围内的所有元素。
  • 使用 uninitialized_copy 在该内存区块上构建元素。

C++ 标准中规定:要么构建出所有元素,要么(当有一个 copy_constrctor 失败时) 不构建任何东西。

uninitialized_fill

uninitialized_fill 也可以将内存配置和对象的构建行为分开。

如果 [__first,__last) 范围内的每个迭代器都指向未初始化的内存,那么 uninitialized_fill 会在该范围内产生 __x 的复制品。

uninitialized_fill 和 uninitialized_copy 一样要么构建出所有元素,要么当任何一个 copy_constrctor 抛出异常后 ,要将所有已构建的元素析构掉。

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

uninitialized_fill_n

uninitialized_fill_n 也可以将内存配置和对象的构建行为分开。

uninitialized_fill_n 能够为指定范围内的所有元素设定相同的初值 __x

uninitialized_fill_n 要么构建出所有元素,要么当任何一个 copy_constrctor 抛出异常后 ,要将所有已构建的元素析构掉。

扫描二维码关注公众号,回复: 10162668 查看本文章

下面给出 uninitialized_fill_n 的实现细节,uninitialized_copy,uninitialized_fill 的实现与之类似。

template <class _ForwardIter, class _Size, class _Tp>
/*__first 表示初始化空间的起始处;__n 表示初始化空间的大小; __x 表示初始值*/
inline _ForwardIter 
uninitialized_fill_n(_ForwardIter __first, _Size __n, const _Tp& __x)
{
  //@ __VALUE_TYPE 萃取出 first 的value type
  return __uninitialized_fill_n(__first, __n, __x, __VALUE_TYPE(__first));
}

萃取出 first 的 value type 后 进一步判断是否是 POD :

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

POD (Plan Old Data) 也就是纯量型别 (scalar types) 或传统的 C struct 型别。 POD 必然具有 trivial ctor/dtor/copt/assignment 函数。因此对于 POD 最有效率的方法是初值填写方法。而对于非 POD 类型的数据,应该采取最保险安全的做法。

//@ POD 数据类型
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 数据类型
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));
}

猜你喜欢

转载自www.cnblogs.com/xiaojianliu/p/12568664.html
今日推荐