STL源码:内存基本处理工具

        STL定义了五个全局函数,作用于没有初始化空间上。前两个函数时用于构造的constr() 和用于析构的destroy()。另外三个是uninitialized_copy(),uninitialized_fill(),uninitialized_fill_n(),分别对应于高层次函数copy()、fill()、fill_n()——这些都是STL算法,要使用这三个底层次函数,应该包含<memory>,不过SGI将其实现定义于<stl_uninitialized>中。

uninitialized_copy


<pre name="code" class="cpp"><pre name="code" class="cpp"><pre name="code" class="cpp">//如果是POD型别,执行流程会转到以下函数,这是由函数模板的参数推到机制而得

 
 template <class _InputIter, class _ForwardIter>inline _ForwardIter __uninitialized_copy_aux(_InputIter __first, _InputIter __last, _ForwardIter __result, __true_type) // __true_type 是型别,不是变量{ // 是常规类型,可以不一个个执行拷贝构造函数 return copy(__first, __last, __result);} 

<pre name="code" class="cpp"><pre name="code" class="cpp">//如果不是POD型别,执行流程会转到以下函数,这是由函数模板的参数推到机制而得
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 的 place new 访问方式。
        _Construct(&*__cur, *__first);
    return __cur;
  }
  //在失败时,还需要清除构建的对象,这是由 STL 标准控制
  __STL_UNWIND(_Destroy(__result, __cur));
}

// 临时构建的模板函式,用来区分纯量型型别
template <class _InputIter, class _ForwardIter, class _Tp>
inline _ForwardIter
__uninitialized_copy(_InputIter __first, _InputIter __last,
                     _ForwardIter __result, _Tp*)
{
    // 利用 type_traits 分列出数据类型,是否是 POD 
    // POD 意指 Plain Old Data,也就是纯量型別(scalar types)或传统的 C struct 型別。
 
 // POD必然有构造函数、析构函数、拷贝/赋值函数,因此对POD采用最有效的初值填写法, 

//对非POD采用最保险的安全方法
 // POD 具有更高效率的构造方式,即直接从内存复制,而不需要拷贝构造函数。 typedef typename __type_traits<_Tp>::is_POD_type _Is_POD; // 企图利用is_POD()所获取的结果,让编译器做参数推导 return __uninitialized_copy_aux(__first, __last, __result, _Is_POD());}// 通用式,它根据 __VALUE_TYPE 取数值类型
// 参数:first指向输入端的起始位置;
// last指向输入端的结束位置(前闭后开区间)
// 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));}// 这是特例化的,征对 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_copy() 使我们能够将内存的配置与对象的构造行为分离开来。如果作为输出目的地的 [result, result + (last - first)) 范围内的每一个迭代器都指向未初始化区域,则 uninitialized_copy() 会使用 copy constructor,给身为输入来源之 [first, last) 范围内的每一个对象产生一份复制品,放进输出范围中。

        C++标准规格书要求 uninitialized_copy() 具有 “commit  or rollback” 语意,意思是要么“构造出所有必要元素”,要么(当有任何一个 copy constructor失败时)“不构造任何东西”。


uninitialized_fill

       uninitialized_fill() 也能够使我们将内存配置与对象的构造行为分离开来。如果[first, last) 范围内的每个迭代器都指向未初始话的内存,那么uninitialized_fill() 会在该范围内产生 x(上式第三个参数)的复制品。换句话说,该函数会针对操作范围内的每个迭代器i,调用construct(&*i, i),在i所指之处产生x的复制品。

       该函数也要具备“commit or rollback“语意,它要么产生所有必要元素,要么不产生任何元素。如果有任何一个copy constructor丢出异常,该函数必须能够将已经产生的所有元素析构掉。

// 这里是把一个集合的数据 [__first, __last) ,按 __x 值进行填充
// 这里的做法和 uninitialized_copy 一致

// Valid if copy construction is equivalent to assignment, and if the
// destructor is trivial.
<pre name="code" class="cpp"><pre name="code" class="cpp"><pre name="code" class="cpp"><pre name="code" class="cpp">//如果是POD型别,执行流程会转到以下函数,这是由函数模板的参数推到机制而得

 
 
 template <class _ForwardIter, class _Tp>inline void__uninitialized_fill_aux(_ForwardIter __first, _ForwardIter __last, const _Tp& __x, __true_type){ fill(__first, __last, __x);} 

<pre name="code" class="cpp"><pre name="code" class="cpp"><pre name="code" class="cpp">//如果不是POD型别,执行流程会转到以下函数,这是由函数模板的参数推到机制而得
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); // place new , __x 是常量的引用传递
  }
  __STL_UNWIND(_Destroy(__first, __cur)); // 出事了? STL 标准要求删除所有已构建的对象实例
}

<pre name="code" class="cpp">//该函数先取出first的value type,然后判断该型别是否为POD型别
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()函数源码,接受三个参数: 

//_first指向输出端(欲初始化空间)的起始处
//_last指向输出端(欲初始化空间)的结束处(前闭后开区间)
//_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));}
 

uninitialized_fill_n

         uninitialized_fill_n() 能够使我们将内存配置与对象构造行为分离开来。它会为指定范围内的所有元素设定相同的初值。如果 [ first, first + n) 范围内的每一个迭代器都指向未初始化的内存,那么 uninitialized_fill_n() 会调用 copy constructor,在该范围内产生 x(上式第三个参数)的复制品。       

        uninitialized_fill_n() 也具有 "commit  or  rollback"语意。

// 这个模板填充一个集合,其成员从 [ __first, __first + n ) 
// 内容统一设置成 __x
// 实作技法同上
    // 利用 type_traits 分列出数据类型,是否是 POD 
    // POD 意指 Plain Old Data,也就是纯量型別(scalar types)或传统的 C struct 型別。
    // POD必然有构造函数、析构函数、拷贝/赋值函数,因此对POD采用最有效的初值填写法,
    //对非POD采用最保险的安全方法
    // POD 具有更高效率的构造方式,即直接从内存复制,而不需要拷贝构造函数。
<pre name="code" class="cpp">//如果拷贝构造函数等同于赋值,而且destructor是trivial,以下就有效
//如果是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);}
<pre name="code" class="cpp">//如果不是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));
}

 //该函数先取出first的value type,然后判断该型别是否为POD型别 

//value_type参见本系列文章《STL源码:STL迭代器》
template <class _ForwardIter, class _Size, class _Tp, class _Tp1>inline _ForwardIter __uninitialized_fill_n(_ForwardIter __first, _Size __n, const _Tp& __x, _Tp1*){
//__type_traits技法参见本系列文章《STL源码:__type_traits》
 typedef typename __type_traits<_Tp1>::is_POD_type _Is_POD; return __uninitialized_fill_n_aux(__first, __n, __x, _Is_POD());}
//该函数接受三个参数:迭代器_first指向欲初始化空间的起始处;
//_n表示欲初始化空间的大小;_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的value_type
}
 


三个内存基本函数的泛型版本与特化版本


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值