3.迭代器和仿函数
来源:互联网 发布:手机限制安装软件 编辑:程序博客网 时间:2024/06/05 10:51
有五种类型的迭代器:
1.Input迭代器:向前读取 istream
2.Output迭代器:向前写入 ostream ,iterator
3.Forward迭代器:向前读取和写入
4.Bidirectional迭代器:向前和向后读取和写入 list,set,multiset,map,multimap
5.Random access迭代器:随机存取,可读取也可写入 vector,deque,string,array
只有在面对Random access迭代器时,才可以使用 <作为循环结束与否的判断准则。
C++标准程序库为迭代器提供了三个辅助函数:advance(),distance(),和iter_swap()。前二者提供所有迭代器只有Random access迭代器才有的能力:前进或后退多个元素,及处理迭代器之间的距离。第三个辅助函数允许你交换两个迭代器的值。
1.void advance(InputIterartor &pos,Dist n):使名为pos的迭代器前进或后退n个元素。
2.Dist distance(InputIterator pos1,InputIterator pos2):返回两个迭代器之间的距离。对于Random access迭代器,结果可以为负。
值得注意的是,处理两个non-Random Access迭代器直接的距离的时候,第一个迭代器绝对不能位于第二个迭代器之后,否则会导致未定义的行为。如果不知道哪个迭代器在前,可以分别算出两个迭代器到起点的距离,在根据这两个距离来判断。
3.void iter_swap(ForwardIterator pos1, ForwardIterator pos2):交换迭代器pos1和pos2所指的值。其中容器的类型不一定相同,但是所指的两个值必须可以相互赋值。
前面提到过有三种迭代器配接器。
1.Insert迭代器
2.stream迭代器
3.reverse迭代器
关于三种迭代器具体介绍可以参看第一节。这里要提到的是ostream_iterator中第二个参数是分隔符,为const char*类型,如果传递一个string对象进去了,应该调用c_str()成员函数来获得正确的类型。此外,reverse迭代器指向的数值是其正想迭代器的前一个元素,如果要进行转换可以对反向迭代器调用base()函数。
仿函数关键是要定义operator()。
1.仿函数可以当作排序准则( bool operator(T a, T b) )。
这里要特别说明,一般函数不能作为排序准则。
2.仿函数可以拥有自己的内部状态(定义private变量)。
for_each()可以返回一个已经在算法内部变动过的仿函数。下面是求一个序列的平均值:
#include <iostream>#include <vector>#include <string>#include <algorithm>using namespace std;class MeanValue{private:long num;long sum;public://这个构造函数其实可以传参数的,只不过在这里不需要传递参数进来MeanValue():num(0),sum(0){} void operator()(int elem){num++;sum += num;}//求平均数double value() const{return static_cast<double>(sum) / static_cast<double>(num);}};int main(){vector<int> ivec;for(int i = 1; i <= 10; ++i)ivec.push_back(i);MeanValue mv = for_each(ivec.begin(),ivec.end(),MeanValue());cout << mv.value() << endl;return 0;}
C++标准程序库提供了许多预定义的仿函数。仿函数效果negate<type>()-paramplus<type>()param1 + param2minus<type>()param1 - param2multiplies<type>()param1 * param2divides<type>()param1 / param2modulus<type>()param1 % param2equal_to<type>()param1 == param2not_equal_to<type>()param1 != param2less<type>()param1 < param2greater<type>()param1 > param2less_equal<type>()param1 <= param2greater_equal<type>()param1 >= param2logical_not<type>()!paramlogical_and<type>()param1 && param2logical_or<type>()param1 || param2
所谓的”函数接配器“是指能将仿函数和另一个仿函数结合起来的仿函数。如bind2nd(op,value),not1(op)等。
bind2nd是将一个二元仿函数转换为一元仿函数。
如将vector内每一个元素都以其最后一个阿拉伯数字代替:
#include <iostream>#include <algorithm>#include <iterator>#include <vector>#include <functional>using namespace std;using namespace std::placeholders;int main(){vector<int> ivec;for (int i = 10; i <= 14; ++i)ivec.push_back(i);//输出:0 1 2 3 4/*transform(ivec.begin(), ivec.end(), ostream_iterator<int>(cout, " "),bind2nd(modulus<int>(), 10));*/transform(ivec.begin(), ivec.end(), ostream_iterator<int>(cout, " "), bind(modulus<int>(), _1, 10));return 0;}
C++标准程序库还提供了一些额外的函数配接器,可以对容器里的每一个元素调用其成员函数。
如果容器元素是对象,采用mem_fun_ref(op),op是对象的const成员函数。
如果容器元素是对象指针,采用mem_fun(op),op是对象的const成员函数。
特别注意,只能调用const成员函数。C++并没有non-const成员函数提供函数配接器。
for_each(coll.begin(),coll.end(),mem_fun_ref(&Person::Print1));for_each(coll.begin(),coll.end(),bind2nd(mem_fun_ref(&Person::Print2),"person"));
上例中print1是一个没有形参的const成员函数,而print2则是一个带有一个类型为string的形参的const成员函数。
#include <iostream>#include <algorithm>#include <iterator>#include <vector>using namespace std;int main(){vector<vector<int> >v;v.push_back(vector<int>(2));v.push_back(vector<int>(3));v.push_back(vector<int>(7));//输出:2 3 7transform(v.begin(),v.end(),ostream_iterator<int>(cout," "),mem_fun_ref(&vector<int>::size));return 0;}
- 3.迭代器和仿函数
- 仿函数和priority_queue
- 仿射函数和仿射组合
- 仿函数(函数对象)和STL算法
- 谓词函数predicates和仿函数functors
- 仿函数和适配器相关函数
- 红黑树C++模板和仿函数实现
- 《STL源码剖析》仿函数和配接器
- 仿函数和判断式的使用
- 仿函数functor和function adapters
- 仿函数进阶——组合型仿函数和自定可以使用函数配接器的仿函数
- 浅谈:函数指针、仿函数和函数适配…
- 仿函数
- 仿函数
- 仿函数
- 仿函数
- 仿函数
- 仿函数
- 源码下编译 apk 导入三方jar
- c3 Threads - Deadlock
- 串行化
- openssl heartbeed到底是怎么回事?
- 调用Google和百度、雅虎进行站内搜索代码
- 3.迭代器和仿函数
- String与StringBuffer的区别
- jboss之后台管理路径
- 《写给大家看的设计书》读后
- 人工误删除InnoDB ibdata数据文件如何恢复?(没试过)
- C++->大小端转换
- Cocos2d-x环境搭建问题,Visual studio 2012与Visual studio 2013运行项目出现的错误
- java读取EXCEL文件1
- 图像匹配之归一化积相关灰度匹配