一、变动性算法for_each
我们把for_each 即是非变动性算法,也可以算是变动性算法,取决于传入的第三个参数,即函数
指针。如果在函数内对容器元素做了修改,那么就属于变动性算法。
示例1:
#include <iostream> #include <vector> #include <algorithm> using namespace std; void print_element(int n) { cout << n << ' '; } void add_3(int &n) { n += 3; } int main(void) { int a[] = { 1, 2, 3, 4, 5 }; vector<int> v(a, a + 5); 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; return 0; }
运行结果:
1 2 3 4 5
4 5 6 7 8
二、变动性算法源代码分析与使用示例:copy、copy_backward
1、示例1:
#include <iostream> #include <vector> #include <list> #include <algorithm> using namespace std; void print_element(int n) { cout << n << ' '; } void add_3(int &n) { n += 3; } int main(void) { int a[] = { 1, 2, 3, 4, 5 }; vector<int> v(a, a + 5); list<int> l(15); //copy必须事先分配空间 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; return 0; }
2、源代码分析
// TEMPLATE FUNCTION copy 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, ...), arbitrary iterators _DEBUG_RANGE(_First, _Last); for (; _First != _Last; ++_Dest, ++_First) *_Dest = *_First; return (_Dest); } template<class _InIt, class _OutIt> inline _IF_CHK(_OutIt) __CLRCALL_OR_CDECL copy(_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())); } // TEMPLATE FUNCTION copy_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) backwards to [..., _Dest), arbitrary iterators _DEBUG_RANGE(_First, _Last); while (_First != _Last) *--_Dest = *--_Last; return (_Dest); } template < class _BidIt1, class _BidIt2 > inline _IF_CHK(_BidIt2) __CLRCALL_OR_CDECL copy_backward(_BidIt1 _First, _BidIt1 _Last, _BidIt2 _Dest) { // copy [_First, _Last) backwards to [..., _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()); }
(1)copy 调用了_Copy_opt,在此函数内递增迭代器,从前两个参数指定的区间内取出元素并拷贝到对应_Dest位置上。
for (; _First != _Last; ++_Dest, ++_First)
*_Dest = *_First;
(2)copy_backward 调用了_Copy_backward_opt,与copy 不同的是实现反向拷贝,即从尾端开始拷贝,所以是递减迭代器。
while (_First != _Last)
*--_Dest = *--_Last;
三、transfrom
1、示例1:
#include <iostream> #include <vector> #include <list> #include <algorithm> using namespace std; void print_element(int n) { cout << n << ' '; } int fun(int a) { return 2 * a; } int fun2(int a, int b) { return a + b; } int main(void) { int a[] = { 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); //1+4, 2+5 cout << endl; return 0; }
2 4 6 8 10
5 7
2、源代码分析
// TEMPLATE FUNCTION transform WITH UNARY OP 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()); } // TEMPLATE FUNCTION transform WITH BINARY OP 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 // for range checked iterators, this will make sure there is enough space _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()); }
*_Dest = _Func(*_First);
*_Dest = _Func(*_First1, *_First2);
三、replace、replace_copy、replace_copy_if
1、示例1:
#include <iostream> #include <vector> #include <list> #include <algorithm> using namespace std; void print_element(int n) { cout << n << ' '; } bool fun(int a) { return a < 10; } int main(void) { int a[] = { 1, 2, 3, 4, 3 }; vector<int> v(a, a + 5); list<int> l(5); replace(v.begin(), v.end(), 3, 13); //所有的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); //<10的替换成0 for_each(l.begin(), l.end(), print_element); cout << endl; return 0; }
1 2 13 4 13
1 2 13 4 13
1 2 3 4 3
0 0 13 0 13
2、源代码分析
// TEMPLATE FUNCTION replace template < class _FwdIt, class _Ty > inline void _Replace(_FwdIt _First, _FwdIt _Last, const _Ty &_Oldval, const _Ty &_Newval) { // replace each matching _Oldval with _Newval _DEBUG_RANGE(_First, _Last); for (; _First != _Last; ++_First) if (*_First == _Oldval) *_First = _Newval; } template < class _FwdIt, class _Ty > inline void replace(_FwdIt _First, _FwdIt _Last, const _Ty &_Oldval, const _Ty &_Newval) { // replace each matching _Oldval with _Newval _Replace(_CHECKED_BASE(_First), _CHECKED_BASE(_Last), _Oldval, _Newval); } // TEMPLATE FUNCTION replace_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) { // copy replacing each matching _Oldval with _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) { // copy replacing each matching _Oldval with _Newval return _Replace_copy(_CHECKED_BASE(_First), _CHECKED_BASE(_Last), _Dest, _Oldval, _Newval, _Iter_random(_First, _Dest), _STD _Range_checked_iterator_tag()); } // TEMPLATE FUNCTION replace_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) { // copy replacing each satisfying _Pred with _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) { // copy replacing each satisfying _Pred with _Val return _Replace_copy_if(_CHECKED_BASE(_First), _CHECKED_BASE(_Last), _Dest, _Pred, _Val, _Iter_random(_First, _Dest), _STD _Range_checked_iterator_tag()); }
(1)replace 带4个参数,将前两个参数指示的区间元素值为_Oldval 的替换成_Newval。
if (*_First == _Oldval)
*_First = _Newval;
(2)replace_copy 带5个参数,先判断前两个参数指示区间的元素是否是_Oldval,若是则替换成_Newval 赋值到第三个参数指示的区间上,否则直接赋值
*_Dest = *_First == _Oldval ? _Newval : *_First;
replace_copy_if 带5个参数,在每个元素拷贝时先判断是否满足条件(函数返回为真),满足则替换成_Val,否则保持不变。
*_Dest = _Pred(*_First) ? _Val : *_First;
参考:
C++ primer 第四版
Effective C++ 3rd
C++编程规范