日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) >

STL源码剖析 数值算法 copy 算法

發(fā)布時(shí)間:2023/12/13 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 STL源码剖析 数值算法 copy 算法 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
  • copy復(fù)制操作,其操作通過(guò)使用assignment operator 。針對(duì)使用trivial assignment operator的元素型別可以直接使用內(nèi)存直接復(fù)制行為(使用C函數(shù) memove或者memcpy)節(jié)約時(shí)間。
  • 還可以通過(guò)函數(shù)重載(function overloading)、型別特性(type traits)、偏特化(partial specialization)等技巧進(jìn)一步強(qiáng)化效率。

  • copy函數(shù)將[first,last) 內(nèi)的元素復(fù)制到區(qū)間[result,result+(last-first))內(nèi)
  • 返回迭代器指向的是??result+(last-first)
  • 輸入?yún)^(qū)間使用?InputIterator,輸出區(qū)間使用?OutputIterator
  • 注意事項(xiàng):1,result位于[first , last)之內(nèi)的時(shí)候也就是輸出區(qū)間的起頭與輸入?yún)^(qū)間重疊,不能使用copy;如果輸出區(qū)間的尾端和輸入?yún)^(qū)間重疊,就可以使用

  • 上述第二種情況可能出現(xiàn)錯(cuò)誤,是可能。如果輸出區(qū)間的起點(diǎn)位于輸入?yún)^(qū)間內(nèi)部,copy算法可能會(huì)在輸入?yún)^(qū)間的(某些)元素尚未復(fù)制之前就將其覆蓋其值,導(dǎo)致錯(cuò)誤
  • 如果copy算法根據(jù)其所接收的迭代器特性 決定使用memmove()來(lái)執(zhí)行任務(wù),就不會(huì)出現(xiàn)問(wèn)題,因?yàn)閙emmove 會(huì)將整個(gè)輸入?yún)^(qū)間的內(nèi)容復(fù)制下來(lái)就不會(huì)出現(xiàn)覆蓋的危險(xiǎn)
#include <iostream> //std::cout #include <algorithm> //std::fill #include <vector> //std::vector #include <deque>template <class T> struct display{void operator()(const T& value){std::cout << value <<' ';} };int main(){{int ia[] = {0,1,2,3,4,5,6,7,8};//輸出區(qū)間的終點(diǎn)和輸入?yún)^(qū)間出現(xiàn)重疊 沒(méi)有問(wèn)題std::copy(ia+2,ia+7,ia);std::for_each(ia,ia+9,display<int>()); //2 3 4 5 6 5 6 7 8std::cout << std::endl;}{int ia[] = {0,1,2,3,4,5,6,7,8};//輸出區(qū)間的起點(diǎn)和輸入?yún)^(qū)間出現(xiàn)重疊 可能會(huì)出現(xiàn)問(wèn)題std::copy(ia+2,ia+7,ia+4);std::for_each(ia,ia+9,display<int>()); //0 1 2 3 2 3 4 5 6std::cout << std::endl;//本例結(jié)果正確 因?yàn)檎{(diào)用的copy算法使用memmove()執(zhí)行實(shí)際復(fù)制操作}{int ia[] = {0,1,2,3,4,5,6,7,8};std::deque<int>id(ia,ia+9);std::deque<int>::iterator first = id.begin();std::deque<int>::iterator last = id.end();++++first; //advance(first,2) 2std::cout << * first << std::endl;----last; //advance(last,-2) 7std::cout << * last << std::endl;std::deque<int>::iterator result = id.begin();std::cout << *result << std::endl; //0//輸出區(qū)間的終點(diǎn)和輸入?yún)^(qū)間重疊 沒(méi)有問(wèn)題std::copy(first,last,result);std::for_each(id.begin(),id.end(),display<int>()); //2 3 4 5 6 5 6 7 8std::cout << std::endl;}{int ia[] = {0,1,2,3,4,5,6,7,8};std::deque<int>id(ia,ia+9);std::deque<int>::iterator first = id.begin();std::deque<int>::iterator last = id.end();++++first; //advance(first,2) 2std::cout << * first << std::endl;----last; //advance(last,-2)std::cout << * last << std::endl;std::deque<int>::iterator result = id.begin();std::advance(result,4);std::cout << *result << std::endl; //4//輸出區(qū)間的起點(diǎn)和輸入?yún)^(qū)間重疊 可能會(huì)出現(xiàn)問(wèn)題std::copy(first,last,result);std::for_each(id.begin(),id.end(),display<int>()); //0 1 2 3 2 3 4 5 6//STL源碼剖析 此處會(huì)出現(xiàn)錯(cuò)誤,原因在于copy算法不再使用memcove()執(zhí)行實(shí)際的復(fù)制操作//但是實(shí)際沒(méi)有出現(xiàn)錯(cuò)誤std::cout << std::endl;/*2 3 4 5 6 5 6 7 8 0 1 2 3 2 3 4 5 6 2702 3 4 5 6 5 6 7 8 2740 1 2 3 2 3 4 5 6 */}}
  • 使用vector代替上述的deque進(jìn)行測(cè)試復(fù)制結(jié)果是正確的,因?yàn)関ector的迭代器其實(shí)就是個(gè)原生指針
  • copy更改的是迭代器所指向的對(duì)象,并不是修改迭代器本身,他會(huì)為區(qū)間內(nèi)的元素賦予新的數(shù)值,但不是產(chǎn)生新的元素,也不會(huì)改變迭代器的個(gè)數(shù)。即,copy不能用來(lái)將元素插入到空的容器中
  • 使用copy算法配合序列容器的insert_iterator?

?

#include <iostream> //std::cout//完全泛化的版本 template <class InputIterator,class OutputIterator> inline OutputIterator copy(InputIterator first,InputIterator last,OutputIterator result){return __copy_dispatch<InputIterator ,OutputIterator>()(first,last,result); }//兩個(gè)重載函數(shù) 針對(duì)原生指針(視為一種特殊的迭代器)const char* 和 const wchar_t 進(jìn)行內(nèi)存的直接拷貝操作 //特殊版本1 重載形式 const char * inline char* copy(const char* first,const char* last,char* result){std::memmove(result,first,last - first);return result + (last - first); }//特殊版本2 重載形式 const wchar_t * inline wchar_t* copy(const wchar_t* first,const wchar_t* last,wchar_t* result){std::memmove(result,first,sizeof(wchar_t)*(last - first));return result + (last - first); }//copy泛化版本調(diào)用了一個(gè) __copy_dispatch函數(shù),這個(gè)函數(shù)有一個(gè)完全泛化版本和兩個(gè)偏特化版本 //完全泛化版本 //__copy_dispatch完全泛化版本根據(jù)迭代器的種類不同,調(diào)用了不同的__copy(),是因?yàn)椴煌N類的迭代器使用的循環(huán)條件不同,有快有慢 template <class InputIterator,class OutputIterator> struct __copy_dispatch{OutputIterator operator()(InputIterator first,InputIterator last,OutputIterator result){return __copy(first,last,result,iterator_category(first));} };//InputIterator 版本 template <class InputIterator,class OutputIterator> inline OutputIterator __copy(InputIterator first,InputIterator last,OutputIterator result,std::input_iterator_tag){//通過(guò)迭代器的等同與否 決定循環(huán)是否繼續(xù) 速度很慢while(first!=last){*result = *first; //assignment operator++first;++result;}return result; }//RandomAccessIterator 版本 template <class RandomAccessIterator,class OutputIterator> inline OutputIterator __copy(RandomAccessIterator first,RandomAccessIterator last,OutputIterator result,std::random_access_iterator_tag){//劃分新的函數(shù) 為了讓其余地方可以使用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*){//使用n決定循環(huán)的執(zhí)行次數(shù) 速度快Distance n = last - first;while (n>0){*result = *first; //assignment operator++result;++first;n--;}return result; }//偏特化版本1 兩個(gè)參數(shù)的型別都是T* 指針 template<class T> struct __copy_dispatch<T*,T*> {T* operator()(T* first,T* last,T* result){typedef typename __type_traits<T>::has_trival_assignment_operator t;return __copy_t(first,last,result,t());} };//偏特化版本2 第一個(gè)參數(shù)是constT*指針形式 第二個(gè)參數(shù)是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_trival_assignment_operator t;return __copy_t(first,last,result,t());} };//在上述偏特化版本指定參數(shù)類型為T*和const T*只針的前提下進(jìn)一步探測(cè) //探測(cè)指針?biāo)钢锸欠窬邆鋞rivial assignment operator (平凡賦值操作符) //SGI STL通過(guò)使用__type_traits<>編程技巧 和 增加一層間接性 來(lái)區(qū)分不同的 __copy_t()//適用于指針?biāo)笇?duì)象具備 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); }//適用于指針?biāo)笇?duì)象具備 non-trivial assignment operator template <class T> inline T* __copy_t(const T* first,const T* last,T* result,__false_type){//原生指針是一種 RandomAccessIterator 所以交給 __copy_d()完成return __copy_d(first,last,result,(std::ptrdiff_t)0); }

?

總結(jié)

以上是生活随笔為你收集整理的STL源码剖析 数值算法 copy 算法的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。