[c++] Iterators
迭代器(Iterator)是指针(pointer)的泛化,它允许程序员用相同的方式处理不同的数据结构(容器)
性质 depends on various containers,因为其实现就是不同的容器实现各自的迭代器.
需要躲过的坑,野指针。
性能预览
一、基本性质
访问方式
遍历数据
container返回的位置实际上就是智能指针,使用auto就不用罗里吧嗦地写那个长长的 typename。
int main()
{
cout << "Hello World!" << endl;
vector<int> v = {1, 2, 3, 4, 5};
int i = 10;
// If const Containers: v.cbegin(), v.cend()
for (auto p = v.begin(); p != v.end(); p++)
{
i++;
(*p) = i;
cout << (*p) << endl;
}
// 正遍历
/*******************************************/
// 反遍历
for (auto p = v.rbegin(); p != v.rend(); p++)
{
cout << (*p) << endl;
}
return 0;
}
二、Iterator的层级关系
所讨论到的几个迭代器的层次.看起来很像继承是麽?但其实"不是".
但是实际上在STL中,这些并不是通过继承关联的.这些只不过是一些符合条件的集合.
这样的好处是:少去了一个特殊的基类(input iterator);其次,使得内建类型指针可以成为 iterator.
其实只要明白iterator是满足某些特别的功能的集合(包括类和内建类型),就不会觉得是继承了.
三、基本操作
四、避免野 Iterator
要么提前deep copy指针的相关信息,方便之后next.
要么删除的同时返回next.
- 解决方法一
就是ease后对iter进行重新赋值。
// 注意p2的使用
i = 0;
vector<int>::iterator p = v.begin();
vector<int>::iterator p2;
for (; p != v.end(); p++)
{
cout << "i = " << i++ << ", " << (*p) << endl;
p2 = p;
v.erase(p2);
}
- 解决方法二
再使用一个迭代器
// erase之后自动++;不erase则需++
i = 0;
vector<int>::iterator p = v.begin();
for (; p != v.end();)
{
cout << "i = " << i++ << ", " << (*p) << endl;
p = v.erase(p);
}
Iterator(迭代器)分类
一、迭代的个性化需求
在find中,我们要求P必须允许 != ,++和*(P)这三个运算符的操作.
iterator实现上通过struct,然后去实现运算符重载.
template<class P, class T>
P find(P start, P beyond, const T& x) { while( start != beyond && * start != x) ++start; return start; }
二、迭代器的使用
istream_iterator
- 读取输入流
ifstream in("data.in");
std::istream_iterator<int> begin(in);
std::istream_iterator<int> end;
// read the first int
cout << *begin++ << endl;
//skip the 2nd int
++begin;
// read the 3rd int
cout << *begin++ << endl;
while (begin != end)
{
cout << *begin++ << endl;
}
- 插入到容器尾部
back_insert_iterator,顾名思义是个迭代器(后缀iterator),是一个模板类。
ifstream in("data.in");
std::istream_iterator<int> begin(in);
std::istream_iterator<int> end;
vector<int> v;
back_insert_iterator<vector<int>> iter(v);
while (begin != end) // 默认读到 EOF
{
*iter++ = *begin++;
}
cout << "------------------------------\n";
for (auto p = v.begin(); p != v.end(); p++)
{
cout << (*p) << endl;
}
std::back_inserter(v):是一个模板函数,实现在容器尾部插入元素。
vector<string> v;
ifstream in("data.in");
std::copy(istream_iterator<string>(in),
istream_iterator<string>(), // 默认读到 EOF
std::back_inserter(v) );
ostream_iterator
void func_ostream()
{
vector<int> v{1, 2, 3, 4, 5};
ostream_iterator<int> os(cout, ",");
for (const auto &i: v)
{
*os++ = i;
}
}
End.