`
aspnetwinform
  • 浏览: 85074 次
  • 性别: Icon_minigender_2
  • 来自: 武汉
社区版块
存档分类
最新评论

从零开始学C++之STL(六):变动性算法源代码分析与使用示例(copy_backward、 transform、 replace_copy_if 等)

 
阅读更多

首先回顾前面的文章,我们把for_each 归类为非变动性算法,实际上它也可以算是变动性算法,取决于传入的第三个参数,即函数

针。如果在函数内对容器元素做了修改,那么就属于变动性算法。


变动性算法源代码分析与使用示例:


一、copy、copy_backward

C++ Code
<nobr>1<br> 2<br> 3<br> 4<br> 5<br> 6<br> 7<br> 8<br> 9<br> 10<br> 11<br> 12<br> 13<br> 14<br> 15<br> 16<br> 17<br> 18<br> 19<br> 20<br> 21<br> 22<br> 23<br> 24<br> 25<br> 26<br> 27<br> 28<br> 29<br> 30<br> 31<br> 32<br> 33<br> 34<br> 35<br> 36<br> 37<br> 38<br> 39<br> 40<br> 41<br> 42<br> 43<br></nobr>
//TEMPLATEFUNCTIONcopy
template<class_InIt,class_OutIt,class_InOutItCat>
inline
_OutIt__CLRCALL_OR_CDECL_Copy_opt(_InIt_First,_InIt_Last,_OutIt_Dest,
_InOutItCat,_Nonscalar_ptr_iterator_tag,_Range_checked_iterator_tag)
{
//copy[_First,_Last)to[_Dest,...),arbitraryiterators
_DEBUG_RANGE(_First,_Last);
for(;_First!=_Last;++_Dest,++_First)
*_Dest=*_First;
return(_Dest);
}

template<class_InIt,class_OutIt>
inline
_IF_CHK(_OutIt)__CLRCALL_OR_CDECLcopy(_InIt_First,_InIt_Last,_OutIt_Dest)
{
//copy[_First,_Last)to[_Dest,...)
return(_Copy_opt(_CHECKED_BASE(_First),_CHECKED_BASE(_Last),_Dest,
_Iter_random(_First,_Dest),_Ptr_cat(_First,_Dest),_Range_checked_iterator_tag()));
}

//TEMPLATEFUNCTIONcopy_backward
template<class_BidIt1,class_BidIt2,class_InOutItCat>
inline
_BidIt2__CLRCALL_OR_CDECL_Copy_backward_opt(_BidIt1_First,_BidIt1_Last,_BidIt2_Dest,
_InOutItCat,_Nonscalar_ptr_iterator_tag,_Range_checked_iterator_tag)
{
//copy[_First,_Last)backwardsto[...,_Dest),arbitraryiterators
_DEBUG_RANGE(_First,_Last);
while(_First!=_Last)
*--_Dest=*--_Last;
return(_Dest);
}

template<class_BidIt1,
class_BidIt2>inline
_IF_CHK(_BidIt2)__CLRCALL_OR_CDECLcopy_backward(_BidIt1_First,_BidIt1_Last,_BidIt2_Dest)
{
//copy[_First,_Last)backwardsto[...,_Dest)
return_Copy_backward_opt(_CHECKED_BASE(_First),_CHECKED_BASE(_Last),_Dest,
_Iter_random(_First,_Dest),_Ptr_cat(_First,_Dest),_STD_Range_checked_iterator_tag());
}

copy 调用了_Copy_opt,在此函数内递增迭代器,从前两个参数指定的区间内取出元素并拷贝到对应_Dest位置上。


for(;_First!=_Last;++_Dest,++_First)


*_Dest=*_First;


copy_backward 调用了_Copy_backward_opt,与copy 不同的是实现反向拷贝,即从尾端开始拷贝,所以是递减迭代器。


while(_First!=_Last)


*--_Dest=*--_Last;


示例代码1:

C++ Code
<nobr>1<br> 2<br> 3<br> 4<br> 5<br> 6<br> 7<br> 8<br> 9<br> 10<br> 11<br> 12<br> 13<br> 14<br> 15<br> 16<br> 17<br> 18<br> 19<br> 20<br> 21<br> 22<br> 23<br> 24<br> 25<br> 26<br> 27<br> 28<br> 29<br> 30<br> 31<br> 32<br> 33<br> 34<br> 35<br> 36<br> 37<br> 38<br> 39<br> 40<br> 41<br> 42<br> 43<br></nobr>
#include<iostream>
#include<vector>
#include<list>
#include<algorithm>
usingnamespacestd;

voidprint_element(intn)
{
cout<<n<<'';
}

voidadd_3(int&n)
{
n+=3;
}

intmain(void)
{
inta[]={1,2,3,4,5};
vector<int>v(a,a+5);
list<int>l(15);

for_each(v.begin(),v.end(),print_element);
cout<<endl;

for_each(v.begin(),v.end(),add_3);

for_each(v.begin(),v.end(),print_element);
cout<<endl;

for_each(l.begin(),l.end(),print_element);
cout<<endl;

copy(v.begin(),v.end(),l.begin());
for_each(l.begin(),l.end(),print_element);
cout<<endl;

copy_backward(v.begin(),v.end(),l.end());
for_each(l.begin(),l.end(),print_element);
cout<<endl;

return0;
}



二、transfrom

C++ Code
<nobr>1<br> 2<br> 3<br> 4<br> 5<br> 6<br> 7<br> 8<br> 9<br> 10<br> 11<br> 12<br> 13<br> 14<br> 15<br> 16<br> 17<br> 18<br> 19<br> 20<br> 21<br> 22<br> 23<br> 24<br> 25<br> 26<br> 27<br> 28<br> 29<br> 30<br> 31<br> 32<br> 33<br> 34<br> 35<br> 36<br> 37<br> 38<br> 39<br> 40<br> 41<br> 42<br> 43<br> 44<br> 45<br> 46<br> 47<br> 48<br> 49<br> 50<br> 51<br> 52<br> 53<br> 54<br> 55<br> 56<br> 57<br> 58<br> 59<br> 60<br> 61<br> 62<br> 63<br> 64<br> 65<br> 66<br> 67<br> 68<br> 69<br> 70<br></nobr>

//TEMPLATEFUNCTIONtransformWITHUNARYOP
template<class_InIt,class_OutIt,class_Fn1,class_InOutItCat>
inline
_OutIt_Transform(_InIt_First,_InIt_Last,_OutIt_Dest,_Fn1_Func,
_InOutItCat,_Range_checked_iterator_tag)
{
//transform[_First,_Last)with_Func
_DEBUG_RANGE(_First,_Last);
_DEBUG_POINTER(_Dest);
_DEBUG_POINTER(_Func);
for(;_First!=_Last;++_First,++_Dest)
*_Dest=_Func(*_First);
return(_Dest);
}

template<class_InIt,class_OutIt,class_Fn1>
inline
_IF_CHK(_OutIt)transform(_InIt_First,_InIt_Last,_OutIt_Dest,_Fn1_Func)
{
return_Transform(_CHECKED_BASE(_First),_CHECKED_BASE(_Last),_Dest,_Func,
_Iter_random(_First,_Dest),_STD_Range_checked_iterator_tag());
}


//TEMPLATEFUNCTIONtransformWITHBINARYOP
template<class_InIt1,class_InIt2,class_OutIt,class_Fn2,class_InItCats,class_InOutItCat>
inline
_OutIt_Transform(_InIt1_First1,_InIt1_Last1,_InIt2_First2,
_OutIt_Dest,_Fn2_Func,
_InItCats,_InOutItCat,
_Range_checked_iterator_tag,_Range_checked_iterator_tag)
{
//transform[_First1,_Last1)and[_First2,_Last2)with_Func
_DEBUG_RANGE(_First1,_Last1);
_DEBUG_POINTER(_Dest);
_DEBUG_POINTER(_Func);
for(;_First1!=_Last1;++_First1,++_First2,++_Dest)
*_Dest=_Func(*_First1,*_First2);
return(_Dest);
}


template<class_InIt1,class_InIt2,class_OutIt,class_Fn2,class_InOutItCat>
inline
_OutIt_Transform(_InIt1_First1,_InIt1_Last1,_InIt2_First2,
_OutIt_Dest,_Fn2_Func,
random_access_iterator_tag,_InOutItCat,
_Range_checked_iterator_tag,_Range_checked_iterator_tag)
{
//transform[_First1,_Last1)and[_First2,_Last2)with_Func
//forrangecheckediterators,thiswillmakesurethereisenoughspace
_InIt2_Last2=_First2+(_Last1-_First1);
(_Last2);
return_Transform(_First1,_Last1,_CHECKED_BASE(_First2),
_Dest,_Func,
forward_iterator_tag(),forward_iterator_tag(),
_Range_checked_iterator_tag(),_Range_checked_iterator_tag());
}


template<class_InIt1,class_InIt2,class_OutIt,class_Fn2>
inline
_IF_CHK2_(_InIt2,_OutIt,_OutIt)transform(_InIt1_First1,_InIt1_Last1,_InIt2_First2,
_OutIt_Dest,_Fn2_Func)
{
return_Transform(_CHECKED_BASE(_First1),_CHECKED_BASE(_Last1),_First2,_Dest,_Func,
_Iter_random(_First1,_First2),_Iter_random(_First1,_Dest),
_STD_Range_checked_iterator_tag(),_STD_Range_checked_iterator_tag());
}

实际上transfrom 重载了两个版本,一个是四个参数的,即将前两个参数指定区间内的元素执行某种操作(函数内)后拷贝到第三个


参数指示的区间上。而另一个版本是五个参数的,即将两个区间的对应元素进行某种操作后拷贝到第三个区间上去。核心的代码区


别在于下面两行:


*_Dest = _Func(*_First);


*_Dest = _Func(*_First1, *_First2);


示例代码2:

C++ Code
<nobr>1<br> 2<br> 3<br> 4<br> 5<br> 6<br> 7<br> 8<br> 9<br> 10<br> 11<br> 12<br> 13<br> 14<br> 15<br> 16<br> 17<br> 18<br> 19<br> 20<br> 21<br> 22<br> 23<br> 24<br> 25<br> 26<br> 27<br> 28<br> 29<br> 30<br> 31<br> 32<br> 33<br> 34<br> 35<br> 36<br> 37<br> 38<br> 39<br></nobr>
#include<iostream>
#include<vector>
#include<list>
#include<algorithm>
usingnamespacestd;

voidprint_element(intn)
{
cout<<n<<'';
}

intfun(inta)
{
return2*a;
}

intfun2(inta,intb)
{
returna+b;
}

intmain(void)
{
inta[]={1,2,3,4,5};
vector<int>v(a,a+5);

list<int>l(5);
list<int>ll(2);

transform(v.begin(),v.end(),l.begin(),fun);
for_each(l.begin(),l.end(),print_element);
cout<<endl;

transform(v.begin(),v.begin()+2,v.begin()+3,ll.begin(),fun2);
for_each(ll.begin(),ll.end(),print_element);
cout<<endl;

return0;
}

输出为 :

2 4 6 8 10

5 7


三、replace、replace_copy、replace_copy_if

C++ Code
<nobr>1<br> 2<br> 3<br> 4<br> 5<br> 6<br> 7<br> 8<br> 9<br> 10<br> 11<br> 12<br> 13<br> 14<br> 15<br> 16<br> 17<br> 18<br> 19<br> 20<br> 21<br> 22<br> 23<br> 24<br> 25<br> 26<br> 27<br> 28<br> 29<br> 30<br> 31<br> 32<br> 33<br> 34<br> 35<br> 36<br> 37<br> 38<br> 39<br> 40<br> 41<br> 42<br> 43<br> 44<br> 45<br> 46<br> 47<br> 48<br> 49<br> 50<br> 51<br> 52<br> 53<br> 54<br> 55<br> 56<br> 57<br> 58<br> 59<br> 60<br> 61<br> 62<br> 63<br> 64<br> 65<br> 66<br> 67<br> 68<br> 69<br> 70<br> 71<br> 72<br> 73<br> 74<br> 75<br> 76<br> 77<br> 78<br> 79<br></nobr>

//TEMPLATEFUNCTIONreplace
template<class_FwdIt,
class_Ty>inline
void_Replace(_FwdIt_First,_FwdIt_Last,
const_Ty&_Oldval,const_Ty&_Newval)
{
//replaceeachmatching_Oldvalwith_Newval
_DEBUG_RANGE(_First,_Last);
for(;_First!=_Last;++_First)
if(*_First==_Oldval)
*_First=_Newval;
}

template<class_FwdIt,
class_Ty>inline
voidreplace(_FwdIt_First,_FwdIt_Last,
const_Ty&_Oldval,const_Ty&_Newval)
{
//replaceeachmatching_Oldvalwith_Newval
_Replace(_CHECKED_BASE(_First),_CHECKED_BASE(_Last),_Oldval,_Newval);
}


//TEMPLATEFUNCTIONreplace_copy
template<class_InIt,class_OutIt,class_Ty,class_InOutItCat>
inline
_OutIt_Replace_copy(_InIt_First,_InIt_Last,_OutIt_Dest,
const_Ty&_Oldval,const_Ty&_Newval,
_InOutItCat,_Range_checked_iterator_tag)
{
//copyreplacingeachmatching_Oldvalwith_Newval
_DEBUG_RANGE(_First,_Last);
_DEBUG_POINTER(_Dest);
for(;_First!=_Last;++_First,++_Dest)
*_Dest=*_First==_Oldval?_Newval:*_First;
return(_Dest);
}

template<class_InIt,
class_OutIt,
class_Ty>inline
_IF_CHK(_OutIt)replace_copy(_InIt_First,_InIt_Last,_OutIt_Dest,
const_Ty&_Oldval,const_Ty&_Newval)
{
//copyreplacingeachmatching_Oldvalwith_Newval
return_Replace_copy(_CHECKED_BASE(_First),_CHECKED_BASE(_Last),_Dest,_Oldval,_Newval,
_Iter_random(_First,_Dest),_STD_Range_checked_iterator_tag());
}



//TEMPLATEFUNCTIONreplace_copy_if
template<class_InIt,class_OutIt,class_Pr,class_Ty,class_InOutItCat>
inline
_OutIt_Replace_copy_if(_InIt_First,_InIt_Last,_OutIt_Dest,
_Pr_Pred,const_Ty&_Val,_InOutItCat,_Range_checked_iterator_tag)
{
//copyreplacingeachsatisfying_Predwith_Val
_DEBUG_RANGE(_First,_Last);
_DEBUG_POINTER(_Dest);
_DEBUG_POINTER(_Pred);
for(;_First!=_Last;++_First,++_Dest)
*_Dest=_Pred(*_First)?_Val:*_First;
return(_Dest);
}


template<class_InIt,
class_OutIt,
class_Pr,
class_Ty>inline
_IF_CHK(_OutIt)replace_copy_if(_InIt_First,_InIt_Last,_OutIt_Dest,
_Pr_Pred,const_Ty&_Val)
{
//copyreplacingeachsatisfying_Predwith_Val
return_Replace_copy_if(_CHECKED_BASE(_First),_CHECKED_BASE(_Last),_Dest,_Pred,_Val,
_Iter_random(_First,_Dest),_STD_Range_checked_iterator_tag());
}

replace 带4个参数,将前两个参数指示的区间元素值为_Oldval 的替换成_Newval。


if(*_First==_Oldval)


*_First=_Newval;


replace_copy 带5个参数,先将前两个参数指示区间的元素都拷贝到第三个参数指示的区间上,再判断是否执行replace。


*_Dest=*_First==_Oldval?_Newval:*_First; 每个元素拷贝后,判断是_Oldval 则替换,否则还是原值。


replace_copy_if 带5个参数,在每个元素拷贝时先判断是否满足条件(函数返回为真),满足则替换成_Val,否则保持不变。


*_Dest=_Pred(*_First)?_Val:*_First;



示例代码3:

C++ Code
<nobr>1<br> 2<br> 3<br> 4<br> 5<br> 6<br> 7<br> 8<br> 9<br> 10<br> 11<br> 12<br> 13<br> 14<br> 15<br> 16<br> 17<br> 18<br> 19<br> 20<br> 21<br> 22<br> 23<br> 24<br> 25<br> 26<br> 27<br> 28<br> 29<br> 30<br> 31<br> 32<br> 33<br> 34<br> 35<br> 36<br> 37<br> 38<br> 39<br> 40<br></nobr>
#include<iostream>
#include<vector>
#include<list>
#include<algorithm>
usingnamespacestd;

voidprint_element(intn)
{
cout<<n<<'';
}

boolfun(inta)
{
returna<10;
}

intmain(void)
{
inta[]={1,2,3,4,3};
vector<int>v(a,a+5);
list<int>l(5);

replace(v.begin(),v.end(),3,13);
for_each(v.begin(),v.end(),print_element);
cout<<endl;

replace_copy(v.begin(),v.end(),l.begin(),13,3);
for_each(v.begin(),v.end(),print_element);
cout<<endl;

for_each(l.begin(),l.end(),print_element);
cout<<endl;

replace_copy_if(v.begin(),v.end(),l.begin(),fun,0);
for_each(l.begin(),l.end(),print_element);
cout<<endl;


return0;
}

输出为:

1 2 13 4 13

1 2 13 4 13

1 2 3 4 3

0 0 13 0 13


参考:

C++ primer 第四版
Effective C++ 3rd
C++编程规范


分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics