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

0 0
原创粉丝点击