迭代器就像用于访问容器元素的指针。
重要点:
迭代器用于从一个元素遍历到另一个元素,这一过程称为迭代容器。
迭代器的主要优点是为所有容器类型提供通用接口。
迭代器使算法独立于所使用的容器类型。
迭代器提供了一种浏览容器元素的通用方法。
语法
:: iterator; :: const_iterator;
在迭代器上执行的操作:
运算符(*): : " *"运算符返回迭代器指向的当前位置的元素。
运算符(++): : " ++"运算符将迭代器加1、因此,迭代器指向容器的下一个元素。
运算符()和运算符(!=): : 这两个运算符都确定两个迭代器是否指向同一位置。
运算符(=): " ="运算符分配迭代器。
不同的黑白迭代器和指针
迭代器可以是智能指针,可以迭代复杂的数据结构。容器提供其迭代器类型。因此,我们可以说迭代器具有不同容器类型的公共接口。 容器类提供了两个基本成员函数,可用于迭代或遍历容器的元素:
begin(): begin()函数返回一个指向容器第一个元素的迭代器。
end(): end()函数返回一个指向容器的过去-最后一个元素的迭代器。
让我们看一个简单的示例:
#include <iostream>
#include<iterator>
#include<vector>
using namespace std;
int main()
{
std::vector<int> v{1,2,3,4,5};
vector<int>::iterator itr;
for(itr=v.begin();itr!=v.end();itr++)
{
std::cout << *itr <<" ";
}
return 0;
}
输出:
1 2 3 4 5
迭代器类别
可以通过以下方式对迭代器进行分类:
输入迭代器
输出迭代器
前向迭代器
双向迭代器
随机访问迭代器
输入迭代器: 输入迭代器是用于访问容器中的元素,但它不会修改容器的值。 用于输入迭代器的运算符为:
增量运算符(++)
等号运算符()
不等于运算符(!=)
取消引用运算符(*) 输出迭代器: 输出迭代器是用于修改容器值的迭代器,但不会从容器中读取值。因此,我们可以说输出迭代器是仅写迭代器。 用于输出迭代器的运算符是:
增量运算符(++)
分配运算符(=) 转发迭代器: 转发迭代器是用于读取和写入容器的迭代器。这是一个多遍迭代器。 用于正向迭代器的运算符为:
增量运算符(++)
分配运算符(=)
等号运算符(=)
不等于运算符(!=) 双向迭代器: 双向迭代器是一种迭代器,它支持正向迭代器的所有功能,另外还增加了一个功能,即减量运算符(-)。我们可以通过减少迭代器来向后移动。 用于双向迭代器的运算符是:
增量运算符(++)
分配运算符(=)
等号运算符(=)
不等于运算符(!=)
减量运算符(-) 随机访问迭代器: 随机访问迭代器是一种迭代器,可在任意位置对元素进行随机访问。它具有双向迭代器的所有功能,另外还增加了一个功能,即指针添加和指针减法,以提供对元素的随机访问。
迭代器提供商
迭代器类别 | 提供者 |
输入迭代器 | istream |
输出迭代器 | ostream |
前向迭代器 | |
双向迭代器 | List, set, multiset, map, multimap |
随机访问迭代器 | Vector, deque, array |
迭代器及其特征
迭代器 | 访问方法 | 运动方向 | I/O功能 |
输入 | 线性 | 仅转发 | 只读 |
输出 | 线性 | 仅转发 | 只写 |
转发 | 线性 | 仅转发 | 读/写 |
双向 | 线性 | 前进和后退 | 读/写 |
随机 | 随机 | 前进和后退 | 读/写 |
迭代器的缺点
如果我们想同时从一种数据结构转移到另一种数据结构,则迭代器将无法工作。
如果我们要更新要迭代的结构,则迭代器由于其存储位置的方式而不允许我们这样做。
如果我们想在处理列表时回溯,则在这种情况下,迭代器将无法工作。
迭代器的优点
以下是迭代器的优点:
易于编程: 使用迭代器而不是使用下标运算符[]来访问容器的元素很方便。如果我们使用下标operator []访问元素,则需要跟踪运行时添加的元素数量,但是在迭代器的情况下不会发生这种情况。 让我们看一个简单的示例:
#include <iostream>
#include<vector>
#include<iterator>
using namespace std;
int main()
{
vector<int> v{1,2,3,4,5};
vector<int>::iterator itr;
for(int i=0;i<5;i++) // Traversal without using an iterator.
{
cout<<v[i]<<" ";
}
cout<<'\n';
for(itr=v.begin();itr!=v.end();itr++) // Traversal by using an iterator.
{
cout<<*itr<<" ";
}
v.push_back(10);
cout<<'\n';
for(int i=0;i<6;i++)
{
cout<<v[i]<<" ";
}
cout<<'\n';
for(itr=v.begin();itr!=v.end();itr++)
{
cout<<*itr<<" ";
}
return 0;
}
输出:
1 2 3 4 5 1 2 3 4 5 1 2 3 4 5 10 1 2 3 4 5 10
在上面的示例中,我们观察到,如果在不使用迭代器的情况下遍历向量的元素,则需要跟踪容器中添加的元素数量。
代码可重用性: 如果我们使用迭代器,则可以重用代码。在上面的示例中,如果我们用列表替换vector,则下标operator []将无法访问元素,因为列表不支持随机访问。但是,我们使用迭代器访问元素,然后也可以访问列表元素。
动态处理: : C++迭代器提供了动态添加或删除数据的功能。 让我们看一个简单的示例:
#include <iostream>
#include<vector>
#include<iterator>
using namespace std;
int main()
{
vector<int> v{1,2,3,4,5}; // vector declaration
vector<int>::iterator itr;
v.insert(v.begin()+1,10);
for(itr=v.begin();itr!=v.end();itr++)
{
cout<<*itr<<" ";
}
return 0;
}
输出:
1 10 2 3 4 5
在上面的示例中,我们使用insert()函数在第二个位置插入一个新元素,而所有其他元素都移位了一个。
差异b/w随机访问迭代器和其他迭代器
随机访问迭代器与其他迭代器之间最重要的区别是,随机访问迭代器需要'1'步骤来访问元素,而其他迭代器则需要'n'步骤。