C++ STL(第十八篇:算法-- copy)

版权声明:转载请说明来源 https://blog.csdn.net/weixin_39640298/article/details/89576521

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源码剖析》

猜你喜欢

转载自blog.csdn.net/weixin_39640298/article/details/89576521