您的位置:首页 > 编程语言 > C语言/C++

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

2015-03-05 09:52 1126 查看
转:http://blog.csdn.net/jnu_simba/article/details/9469597

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

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

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

一、copy、copy_backward

C++ Code
1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

// 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());

}
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
1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

#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);

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;

}


二、transfrom

C++ Code
1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

// 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());

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

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

别在于下面两行:

*_Dest = _Func(*_First);

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

示例代码2:

C++ Code
1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

#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);

cout << endl;

return 0;

}
输出为 :

2 4 6 8 10

5 7

三、replace、replace_copy、replace_copy_if

C++ Code
1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

// 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());

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

if (*_First == _Oldval)

*_First = _Newval;

replace_copy 带5个参数,先判断前两个参数指示区间的元素是否是_Oldval,若是则替换成_Newval 赋值到第三个参数指示的区间上,否则直接赋值

*_Dest = *_First == _Oldval ? _Newval : *_First;

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

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

示例代码3:

C++ Code
1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

#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);

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;

return 0;

}
输出为:

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++编程规范
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐