【STL源码剖析读书笔记】【第6章】算法之copy算法

        由于copy进行的是复制操作,而复制操作不外乎用assignment operator或copy constructor(copy算法用的是前者),但是某些元素型别拥有的是trivial assginment operator,因此,如果能够使用内存直接复制行为(例如C标准函数memmove或memcpy),便能够节省大量时间。为此,SGI STL的copy算法用尽各种办法,包括函数重载、型别特性、偏特化等编程技巧,无所不用其极地加强效率。如下图所示:


注意:

1)  copy只是将输出区间内的元素赋予新值,不会产生新的元素,所以copy不能直接用来将元素插入空容器中.

2)  copy的输出区间的起点如果位于输入区间内,可能会使copy算法出错。

STL copy函数源码如下:

//SGI STL的copy算法运用函数重载、型别特性、偏特化等编程技巧,无所不用其极地加强效率
//完全泛化版本
template <class InputIterator, class OutputIterator>
inline OutputIterator copy(InputIterator first, InputIterator last,
	OutputIterator result)
{
	return __copy_dispatch<InputIterator, OutputIterator>()(first, last, result);
}
//全特化版本一,底层用memmove,节省时间
inline char* copy(const char* first, const char* last, char* result) {
	memmove(result, first, last - first);
	return result + (last - first);
}
//全特化版本二,底层用memmove,节省时间
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*形式,根据指针所指对象是否具有trivial assignment operator调用不同的__copy_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());
	}
};
//偏特化版本二,第一个参数是const T*形式,第二个参数是T*形式,根据指针所指对象是否具有trivial assignment operator调用不同的__copy_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_trivial_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;
	return result;
}
//RandomIterator版本,调用__copy_d()函数
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));
}
//以n决定循环次数,速度快
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;
}

//适用于指针所指对象具备trivial assignment operator
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);
}
//适用于指针所指对象具备non-trivial assignment operator
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);
}

   

posted on 2015-05-23 13:12  ruan875417  阅读(156)  评论(0编辑  收藏  举报

导航