STL原始碼分析之copy演算法
阿新 • • 發佈:2018-12-08
前言
在前面分析順序容器和關聯容器時, 總會遇到copy
這個函式, 當時並沒有去分析這個函式, 畢竟都能知道他是什麼功能, 本節就來揭開它面紗.
copy分析
copy函式原始碼在stl_algobase.h
中, 該結構中還有很多其他的演算法實現, 我只是從中挑選出了copy, 有興趣可以自己看看裡面的其他演算法.
copy
同traits
程式設計, 都對效能做了最優的優化, 能使用的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_tag
與input_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
類似, 只是反向進行復制.