变动性算法源代码分析与使用示例(copy_backward、 transform、 replace_copy_if 等)

首先回顾前面的文章,我们把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());
}

 

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

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;

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++编程规范

转载于:https://www.cnblogs.com/alantu2018/p/8471423.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/278392.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

[转]QDir类及其用法总结

直接给出原文链接&#xff1a;QDir类及其用法总结 转载于:https://www.cnblogs.com/rainbow70626/p/10330643.html

如何在Outlook中的电子邮件上显示快速操作按钮

There are probably actions you regularly perform in Outlook, such as deleting, archiving, and marking things as read. Here’s how to use Quick Action buttons to add one-click options that appear over every email to perform each action. 您可能会在Outlook中定…

c++读取和写入TXT文件的整理

c读取和写入TXT文件的整理 #include "stdafx.h" #include <iostream> //无论读写都要包含<fstream>头文件 #include <fstream> #include <iomanip> using namespace std;int main() {//ifstream从文件流向内存的ifstream表示文件输入流…

使用RestTemplate时报错java.lang.IllegalStateException: No instances available for 127.0.0.1

我在RestTemplate的配置类里使用了 LoadBalancedComponentpublic class RestTemplateConfig { Bean LoadBalanced public RestTemplate restTemplate(){ return new RestTemplate(); }}或者 再调用Autowiredprivate RestTemplate restTemplate;必须使用应用名作为代替ip:端口&a…

sh变量特性(3)默认特性

变量说明$0当前脚本的文件名$n传递给脚本或函数的参数&#xff0c;n是数字&#xff0c;第n个参数$#传递给脚本或函数的参数个数$*传递给脚本或函数的所有参数$传递给脚本或函数的所有参数。被””包含时&#xff0c;与$*稍有不同$?上个命令的退出状态&#xff0c;或函数返回值…

zune linux_更新您的Zune Player软件

zune linuxKeeping your computer and software up to date is very important in keeping everything running smooth and secure. It’s also important to keep your geeky gadgets updated as well. Here we take a look at updating a Zune HD. 保持计算机和软件的最新状态…

继承的几种方式

1.借助构造函数实现继承 function Parent() { this.name parent } Parent.prototype.say function () { // 不能被继承 this.say function() { console.log(hello this.name) } } function Child() { Parent.call(this) this.type child } console.log(new Child) // 没有参…

写一个简单的 django_post demo

1.新建一个django工程&#xff0c;其路由为下图 2.要做的是一个 简单的登录请求&#xff0c;以表单形式提交&#xff0c;html 部分代码如下 这里注意action指向的是路由的地址&#xff0c;index1后的views.login部分代码如下 这段代码指的是&#xff0c;如果login接收到的请求是…

日志收集

2019独角兽企业重金招聘Python工程师标准>>> ELK (ElasticSearch、Logstash、Kibana)&#xff1a; https://my.oschina.net/itblog/blog/547250 转载于:https://my.oschina.net/zfscofield/blog/1625703

autocopy2u_借助AutoCopy简化Firefox中的文本复制和粘贴

autocopy2uLooking for an easy way to speed up copying and pasting in Firefox? Now you can reduce the amount of work that you have to do by half with AutoCopy. 是否在寻找一种简便的方法来加快Firefox中的复制和粘贴&#xff1f; 现在&#xff0c;您可以使用自动复…

virtualenv模块使用

开发多个应用&#xff1a; 如A需要jinja2.7开发&#xff1b;如B需要jinja2.6开发。或者C需要Python2.7开发&#xff0c;D需要Python3.5开发 那么解决上述问题就需要使用virtualenv这个模块&#xff1a; 它的作用是&#xff1a;创建“隔离”环境&#xff0c;使项目拥有独立的Pyt…

僵尸进程处理方式

Linux服务器上&#xff0c;多少会出现一些僵尸进程&#xff0c;下面介绍如何快速寻找和消灭这些僵尸进程的方法 首先&#xff0c;我们可以用top命令来查看服务器当前是否有僵尸进程&#xff0c;在下图中可以看到僵尸进程数的提示&#xff0c;如果数字大于0&#xff0c;那么意味…

chromebook刷机_如何查看Chromebook的停产日期

chromebook刷机Google谷歌There comes a time in your Chromebook’s life when it no longer receives updates from Google. It’s inevitable and could be a lot sooner than you think. Here’s how to see your Chromebook’s scheduled end-of-life date. Chromebook一生…

C#将unix时间戳转换成.net的DateTime类型的代码

下面的内容是关于C#将unix时间戳转换成.net的DateTime类型的内容。 DateTime epoch new DateTime(1970,1,1,0,0,0,0, DateTimeKind.Utc);DateTime myDate epoch.AddSeconds(1258598728).toLocalTime(); 转载于:https://www.cnblogs.com/odsxe/p/10338494.html

【活动】AI人工智能技术沙龙 |杭州站

AI人工智能技术沙龙 |杭州站将于2018年3月3号在浙江杭州市文一西路1818-2号中国&#xff08;杭州&#xff09;人工智能小镇举办由袋鼠云、七牛云及“因特链”社区的老师为大家带来AI纯技术干货分享另有区块链和AI人工智能技术融合技术主题1活动安排时间&#xff1a;2018年3月3号…

如何在Google文档中的图片周围换行

If you want to insert an image or object into a document, it’s relatively simple. However, positioning and getting them to stay where you want can be frustrating. The wrap text feature in Google Docs makes all of this more manageable. 如果要将图像或对象插…

mysql的left函数

1、LEFT()函数是一个字符串函数&#xff0c;它返回具有指定长度的字符串的左边部分。 LEFT(Str,length); 接收两个参数&#xff1a; str&#xff1a;一个字符串&#xff1b; length&#xff1a;想要截取的长度&#xff0c;是一个正整数&#xff1b; 2、示例&#xff1a; SELECT…

如何在Linux上使用history命令

Fatmawati Achmad Zaenuri/ShutterstockFatmawati Achmad Zaenuri / ShutterstockLinux’s shell saves a history of the commands you run, and you can search it to repeat commands you’ve run in the past. Once you understand the Linux history command and how to u…

mysql导入sqlserver数据库表

原文&#xff1a;https://zhidao.baidu.com/question/1114325744502691499.html 在Navicat for MySQL 管理器中&#xff0c;创建目标数据库(注意&#xff1a;因为是点对点的数据导入&#xff0c;要求sql server 中要导出的数据库名称和要导入到Mysql 中的数据库的名字相同)点击…

AppleScript

AppleScript 后缀名scpt do shell script "shell脚本"转载于:https://www.cnblogs.com/yangwenhuan/p/10338580.html