有五种类型的迭代器:
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>() | -param |
plus<type>() | param1 + param2 |
minus<type>() | param1 - param2 |
multiplies<type>() | param1 * param2 |
divides<type>() | param1 / param2 |
modulus<type>() | param1 % param2 |
equal_to<type>() | param1 == param2 |
not_equal_to<type>() | param1 != param2 |
less<type>() | param1 < param2 |
greater<type>() | param1 > param2 |
less_equal<type>() | param1 <= param2 |
greater_equal<type>() | param1 >= param2 |
logical_not<type>() | !param |
logical_and<type>() | param1 && param2 |
logical_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 7
transform(v.begin(),v.end(),ostream_iterator<int>(cout," "),
mem_fun_ref(&vector<int>::size));
return 0;
}