《STL源码剖析》—— 空间配置器(五)

一、内存基本处理工具

        STL定义有五个全局函数,作用于未初始化空间上。前两个函数是用于构造的 construct() 和用于析构的 destroy(),另三个函数 uninitialized_copy(),uninitialized_fill(),uninitialized_fill_n(),分别对应于高层次函数 copy()、fill()、fill_n() —— 这些都是STL算法。SGI把它们都定义于<stl_uninitialized>。

        1. uninitialized_copy

// 如果 copy construction 等同于 assignment,而且 destructor 是 trivial,以下就有效
template <class InputIterator, class ForwardIterator>
inline ForwardIterator 
__uninitialized_copy_aux(InputIterator first, InputIterator last,
                         ForwardIterator result,
                         __true_type) {
  return copy(first, last, result); // 调用 STL 算法 copy()
}

template <class InputIterator, class ForwardIterator>
ForwardIterator 
__uninitialized_copy_aux(InputIterator first, InputIterator last,
                         ForwardIterator result,
                         __false_type) {
  ForwardIterator cur = result;
  __STL_TRY {
    for ( ; first != last; ++first, ++cur)
      construct(&*cur, *first); // 必须一个一个元素地构造,无法批量进行
    return cur;
  }
  __STL_UNWIND(destroy(result, cur));
}

// POD 意指 Plain Old Data,也就是标量型别(scalar types)或传统的 C struct 型别。
// POD 型别必然拥有 trivial ctor/dtor/copy/assignment函数。
template <class InputIterator, class ForwardIterator, class T>
inline ForwardIterator
__uninitialized_copy(InputIterator first, InputIterator last,
                     ForwardIterator result, T*) {
  typedef typename __type_traits<T>::is_POD_type is_POD;
  return __uninitialized_copy_aux(first, last, result, is_POD());
  // 利用 is_POD() 所获得的结果,让编译器做参数推导
}

template <class InputIterator, class ForwardIterator>
inline ForwardIterator
  uninitialized_copy(InputIterator first, InputIterator last,
                     ForwardIterator result) {
  return __uninitialized_copy(first, last, result, value_type(result));
  // 利用 value_type() 取出 result 的 value type
}

// 针对 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失败时)“不构造任何东西”。

        2. uninitialized_fill

template <class ForwardIterator, class T>
inline void
__uninitialized_fill_aux(ForwardIterator first, ForwardIterator last, 
                         const T& x, __true_type)
{
  fill(first, last, x);
}

template <class ForwardIterator, class T>
void
__uninitialized_fill_aux(ForwardIterator first, ForwardIterator last, 
                         const T& x, __false_type)
{
  ForwardIterator cur = first;
  __STL_TRY {
    for ( ; cur != last; ++cur)
      construct(&*cur, x);
  }
  __STL_UNWIND(destroy(first, cur));
}

template <class ForwardIterator, class T, class T1>
inline void __uninitialized_fill(ForwardIterator first, ForwardIterator last, 
                                 const T& x, T1*) {
  typedef typename __type_traits<T1>::is_POD_type is_POD;
  __uninitialized_fill_aux(first, last, x, is_POD());
                   
}

template <class ForwardIterator, class T>
inline void uninitialized_fill(ForwardIterator first, ForwardIterator last, 
                               const T& x) {
  __uninitialized_fill(first, last, x, value_type(first));
}
        uninitialized_fill() 也能够使我们将内存配置与对象的构造行为分离开来。如果[first, last) 范围内的每个迭代器都指向未初始话的内存,那么uninitialized_fill() 会在该范围内产生 x(上式第三个参数)的复制品。

        与 uninitialized_copy() 一样,uninitialized_fill() 必须具备 “commit or rollback” 语意。

        3. uninitialized_fill_n

template <class ForwardIterator, class Size, class T>
inline ForwardIterator
__uninitialized_fill_n_aux(ForwardIterator first, Size n,
                           const T& x, __true_type) {
  return fill_n(first, n, x);
}

template <class ForwardIterator, class Size, class T>
ForwardIterator
__uninitialized_fill_n_aux(ForwardIterator first, Size n,
                           const T& x, __false_type) {
  ForwardIterator cur = first;
  __STL_TRY {
    for ( ; n > 0; --n, ++cur)
      construct(&*cur, x);
    return cur;
  }
  __STL_UNWIND(destroy(first, cur));
}

template <class ForwardIterator, class Size, class T, class T1>
inline ForwardIterator __uninitialized_fill_n(ForwardIterator first, Size n,
                                              const T& x, T1*) {
  typedef typename __type_traits<T1>::is_POD_type is_POD;
  return __uninitialized_fill_n_aux(first, n, x, is_POD());
                                    
}

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

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

你可能感兴趣的:(C++,STL)