zoukankan      html  css  js  c++  java
  • 【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);
    }

       

  • 相关阅读:
    2018.12.30【NOIP提高组】模拟赛C组总结
    【NOIP2007提高组】矩阵取数游戏
    【NOIP2007提高组】字符串的展开
    【NOIP2007提高组】统计数字
    2018.12.22【NOIP提高组】模拟B组总结
    【NOIP2013模拟11.5A组】cza的蛋糕(cake)
    CDQ分治总结
    O(2),O(3),Ofast 手动开[吸氧]
    【NOIP2013模拟11.6A组】灵能矩阵(pylon)
    【GDKOI2012模拟02.01】数字
  • 原文地址:https://www.cnblogs.com/ruan875417/p/4558305.html
Copyright © 2011-2022 走看看