1. 程式人生 > >STL原始碼分析之copy演算法

STL原始碼分析之copy演算法

前言

在前面分析順序容器和關聯容器時, 總會遇到copy這個函式, 當時並沒有去分析這個函式, 畢竟都能知道他是什麼功能, 本節就來揭開它面紗.

copy分析

copy函式原始碼在stl_algobase.h中, 該結構中還有很多其他的演算法實現, 我只是從中挑選出了copy, 有興趣可以自己看看裡面的其他演算法.

copytraits程式設計, 都對效能做了最優的優化, 能使用的memmove函式就使用它, 不能通過迭代器型別再來選擇最優處理.

在偏特化與全特化中分析過, 最適合的函式會優先呼叫, 普通函式優先順序大於模板函式

template <
class InputIterator, class OutputIterator> inline OutputIterator copy(InputIterator first, InputIterator last, OutputIterator result) { return __copy_dispatch<InputIterator,OutputIterator>()(first, last, result); } // 過載 // 在偏特化與全特化中分析過, 最適合的函式會優先呼叫, 普通函式優於模板函式 inline char* copy(const char* first,
const char* last, char* result) { // 直接呼叫memmove效率最高 memmove(result, first, last - first); return result + (last - first); } inline wchar_t* copy(const wchar_t* first, const wchar_t* last, wchar_t* result) { // 直接呼叫memmove效率最高 memmove(result, first, sizeof(wchar_t) * (last - first)); return
result + (last - first); }

__copy_dispatch 通過傳入引數的迭代器型別再進行優化處理

template <class InputIterator, class OutputIterator>
struct __copy_dispatch
{
  OutputIterator operator()(InputIterator first, InputIterator last,
                            OutputIterator result) {
      // iterator_category獲取迭代器型別, 不同迭代器選擇不同的過載函式
    return __copy(first, last, result, iterator_category(first));
  }
};

輸入迭代器型別處理 input_iterator_tag

template <class InputIterator, class OutputIterator>
inline OutputIterator __copy(InputIterator first, InputIterator last,
                             OutputIterator result, input_iterator_tag)
{
    // 通過迭代器將一個元素一個元素的複製
  for ( ; first != last; ++result, ++first)
    *result = *first;
  return result;
}

隨機訪問迭代器型別處理 random_access_iterator_tag

template <class RandomAccessIterator, class OutputIterator>
inline OutputIterator 
__copy(RandomAccessIterator first, RandomAccessIterator last, OutputIterator result, random_access_iterator_tag)
{
  return __copy_d(first, last, result, distance_type(first));
}

template <class RandomAccessIterator, class OutputIterator, class Distance>
inline OutputIterator
__copy_d(RandomAccessIterator first, RandomAccessIterator last,
         OutputIterator result, Distance*)
{
    // 通過迭代器之間的元素個數將一個元素一個元素的複製
  for (Distance n = last - first; n > 0; --n, ++result, ++first) 
    *result = *first;
  return result;
}

random_access_iterator_taginput_iterator_tag不同就在於前者不使用迭代器遍歷, 後者使用的是迭代器訪問. 使用迭代器的效率要低一點, 畢竟可能是RB-tree的迭代器, 連結串列的迭代器之類的.

全特化處理 針對指標, const型別又做了特化處理

template <class T>
struct __copy_dispatch<const T*, T*>
{
  T* operator()(const T* first, const T* last, T* result) {
    typedef typename __type_traits<T>::has_trivial_assignment_operator t; 
    return __copy_t(first, last, result, t());
  }
};

template <class T>
struct __copy_dispatch<T*, T*>
{
  T* operator()(T* first, T* last, T* result) {
    typedef typename __type_traits<T>::has_trivial_assignment_operator t; 
    return __copy_t(first, last, result, t());
  }
};

優化處理

template <class T>
inline T* __copy_t(const T* first, const T* last, T* result, __false_type) {
  return __copy_d(first, last, result, (ptrdiff_t*) 0);
}

優化處理

template <class T>
inline T* __copy_t(const T* first, const T* last, T* result, __true_type) {
  memmove(result, first, sizeof(T) * (last - first));
  return result + (last - first);
}

針對pair型別

template <class InputIterator, class Size, class OutputIterator>
pair<InputIterator, OutputIterator> __copy_n(InputIterator first, Size count,
                                             OutputIterator result,
                                             input_iterator_tag) {
  for ( ; count > 0; --count, ++first, ++result)
    *result = *first;
  return pair<InputIterator, OutputIterator>(first, result);
}

template <class RandomAccessIterator, class Size, class OutputIterator>
inline pair<RandomAccessIterator, OutputIterator>
__copy_n(RandomAccessIterator first, Size count,
         OutputIterator result,
         random_access_iterator_tag) {
  RandomAccessIterator last = first + count;
  return pair<RandomAccessIterator, OutputIterator>(last,
                                                    copy(first, last, result));
}

總結

本節分析了copy對優化的處理, 針對不同的型別, 不同迭代器選擇最優的處理函式, 提高程式的效率, STL的強大到處可以體現. __copy_backward我沒有做分析, 他同copy類似, 只是反向進行復制.