C++ STL(第十八篇:算法-- copy)
1、copy算法
不管在什么地方,copy() 都是一个常常被调用的函数。copy操作不外乎运用 赋值操作 或 拷贝构造 来进行,但是某些元素能够使用内存直接复制行为,能够提高效率,节省时间。
copy() 算法可将输入区间 [first, last) 内的元素赋值到输出区间 [result, result+(last-first)) 内。copy 算法用了各种办法来提高效率,包括函数重载、型别特性、偏特化等编程技巧,如下图所示:
现在看一下 copy 算法的代码:
//唯一对外接口
template<class InputIterator, class OutputIterator>
inline OutputIterator copy(InputIterator first, InputIterator last, OutputIterator result)
{
return __copy_dispatch<InputIterator,OutputIterator>()( first, last, result);
}
下面是两个重载函数,针对原生指针const char* 和 const wchar_t*,进行内存直接拷贝操作:
inline char* copy(const char* first, const char* last, char* result)
{
mommove(result, first, last-first);
return result + (last - first);
}
inline wchar_t* copy(const wchar_t* first, const wchar_t* last, wchar_t* result)
{
memmove(result, first, sizeof(wchar_t) * (last - first));
return result + (last - first);
}
copy 函数的泛化版本调用了一个 __copy_dispatch() 函数,此函数有一个完全泛化版本和两个偏特化版本:
template<class InputIterator, class OutputIterator>
struct __copy_dispatch
{
OutputIterator operator()(InputIterator first, InputIterator last, OutputIterator result)
{
return __copy(first, last, result, iterator_category(first));
}
}
//偏特化版本,两个参数都是T* 指针形式
template<class T>
struct __copy_dispatch<T*, T*>
{
T* operator()(T* first, T* last, T* result)
{
//模板元编程,判断是否具有“平凡赋值操作符”
typedef typename __type_traits<T>::has_tivial_assignment_operator t;
return __copy_T(first, last, result, t());
}
}
//偏特化版本,第一个参数为 const T* 指针形式,第二参数为 T* 指针形式
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_tivial_assignment_operator t;
return __copy_T(first, last, result, t());
}
}
__copy_dispatch() 的完全泛化版根据迭代器种类的不同,调用了不同的 __copy(),为的是不同种类的迭代器所使用的循环条件不同,有快慢之别。
//InputIterator 版本
template<class InputIterator, class OutputIterator>
inline OutputIterator __copy(InputIterator first, InputIterator last, OutputIterator result, input_iterator_tag)
{
//以迭代器决定循环是否继续 速度慢
for( ; first != last; ++result, ++first)
*result = *first; //assignment operator
return result;
}
//RandomAccessIterator 版本
template<class RandomAccessIterator, class OutputIterator>
inline OutputIterator __copy(RandomAccessIterator first, RandomAccessIterator last, OutputIterator result,random_access_iterator_tag)
{
typename Distance = distance_type(first);
//以 n 决定循环的执行次数,速度快
for(Distance n = last - first; n>0; --n, ++result, ++first)
*result = *first;
return result;
}
而上面进行分支的两个偏特化版本,是在“参数为原生指针形式” 的前提下,希望进一步探测 “指针所指之物是否具有 trivial assignment operator(平凡赋值操作符)”。这一点会对效率有影响。
//适用于 “指针所指之对象具备 trivial assignment operator”
template<class T>
intline T* __copy_t(const T* first, const T* last, T* result, __true_type)
{
memove(result, first, sizeof(T) * (last - first));
return result + (last - first);
}
//适用于 “指针所指对象具备 non-trivial assignment operator”
template<class T>
intline T* __copy_t(const T* first, const T* last, T* result, __false_type)
{
typename Distance = distance_type(first);
for(Distance n = last - first; n>0; --n, ++result, ++first)
*result = *first;
return result;
}
2、copy_backward
copy_backwar 和 copy 十分类似,是将 [first, last) 区间内的每一个元素,以逆行的方向复制到以 result-1 为起点,方向亦为逆行的区间上。如下图所示:
因为copy_backward的代码和 copy 的机器相似,这里就不列出了。
3、其它基本算法
这里列举一下一些简单的基本算法,主要说一下名字,和它们的作用。
equal 如果两个序列在 [first,last) 区间内相等,equal() 返回true。如果第二个序列的元素比较多,多出来的元素不予考虑。
template<class InputIterator1, class InputIterator2>
inline bool equal(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2)
{
for( ; first1 != last1; ++first1,++first2)
if( *first1 != first2)
return false;
return true;
}
fill 将 [first, last) 内的所有元素改填新值。
template<class ForwardIterator, class T>
void fill(ForwardIterator first, ForwardIterator last, const T& value)
{
for( ; first != last; ++first)
*first = value;
}
fill_n 将 [first, last) 内的前n个元素改填新值,返回的迭代器指向被填入的最后一个元素的下一个位置。
template<class OutputIterator, class Size, class T>
OutputIterator fill_n(OutputIterator first, Size n, const T& value)
{
for( ;n > 0; --n,++first)
*first = value;
return first;
}
iter_swap 将两个 ForwardIterator 所指的对象对调。
template<class ForwardIterator1, class ForwardIterator2>
inline void iter_swap(ForwardIteator1 a, ForwardIterator2 b)
{
__iter_swap(a, b, value_type(a)); //第三个参数为型别
}
template<class ForwardIterator1, class ForwardIterator2, class T>
inline void __iter_swap(ForwardIterator1 a, ForwardIteator2 b, T*)
{
T tmp = *a;
*a = *b;
*b = temp;
}
max 取两个对象的较大值。
template<class T>
inline const T& max( const T& a, const T& b)
{
return a < b ? b : a;
}
min 取两个对象中的较小值。
template<class T>
inline const T& min(const T& a, const T& b)
{
return b < a ? b : a;
}
mismath 用来平行比较两个序列,指出两者之间的第一个不匹配点。返回一对迭代器,分别指向两个序列中的不匹配点。
template<class InputIterator1, class InputIterator2>
pair<InputIterator1,InputIterator2> mismatch(InputIterator1 first1, InputIterator1 last1, InputIerator2 first2)
{
while( first1 != last1 && *first1 == *first2)
{
++first1;
++first2;
}
return pair<InputIterator1,InputIterator2>(first1,first2);
}
好了今天就整理这么多了,回家睡觉去了~
感谢大家,我是假装很努力的YoungYangD(小羊)。
参考资料:
《STL源码剖析》