迭代器
迭代器是一个对象,可以循环访问 C++ 标准库容器中的元素,并提供对各个元素的访问。 C++ 标准库容器全都提供迭代器,以便算法可以采用标准方式访问其元素,而不必考虑用于存储元素的容器类型。
可通过使用成员和全局函数(如 begin()
和 end()
)以及运算符(如 ++
和 --
)向前或向后移动,来显式使用迭代器。 还可通过范围 for 循环或(对于某些迭代器类型)下标运算符 []
,来隐式使用迭代器。
在 C++ 标准库中,序列或范围的开头是第一个元素。 序列或范围的末尾始终定义为最后一个元素的下一个位置。 全局函数 begin
和 end
会将迭代器返回到指定容器。 典型显式迭代器循环访问容器中的所有元素,如下所示:
vector<int> vec{ 0,1,2,3,4 };
for (auto it = begin(vec); it != end(vec); it++)
{
// Access element using dereference operator
cout << *it << " ";
}
可以使用范围 for 循环更加简单地完成相同操作:
for (auto num : vec)
{
// no dereference operator
cout << num << " ";
}
有五种类别的迭代器。 这些类别如下所示(按功能逐渐增强的顺序):
输出。 输出迭代器
X
可以使用运算符循环访问序列++
,并且只能使用*
运算符编写一次元素。输入。 输入迭代器
X
可以使用运算符循环访问序列++
,并且可以使用*
运算符读取元素任意次数。 可使用==
和!=
运算符来比较输入迭代器。 递增输入迭代器的任何副本后,无法安全地比较、取消引用或递增其他任何副本。转发。 转发迭代器
X
可以使用 ++ 运算符循环访问序列,并且可以使用运算符读取任何元素或写入非常量元素的次数*
。 可使用->
运算符访问元素成员,使用==
和!=
运算符比较向前迭代器。 可以创建向前迭代器的多个副本,其中每个副本都可以独立地取消引用和递增。 未使用对任何容器的引用进行初始化的向前迭代器称为 null 向前迭代器。 Null 向前迭代器的比较结果始终是相等的。双向。 双向迭代器
X
可以取代向前迭代器。 但是,还可以递减双向迭代器例如在--X
、X--
或(V = *X--)
中。 可以采用与向前迭代器相同的方式访问元素成员和比较双向迭代器。随机访问。 随机访问迭代器
X
可以取代双向迭代器。 借助随机访问迭代器,可以使用下标运算符[]
访问元素。 可使用+
、-
、+=
和-=
运算符向前或向后移动指定数量的元素并计算迭代器之间的距离。 可使用==
、!=
、<
、>
、<=
和>=
比较双向迭代器。
可以分配或复制所有迭代器。 它们被假定为轻量对象,通常按值(而不是按引用)进行传递和返回。 另请注意,前面所述的操作都无法在对有效迭代器执行时引发异常。
可以通过显示三个序列来汇总迭代器类别的层次结构。 若要对序列进行只写访问,可以使用以下任何项:
输出迭代器
-> 向前迭代器
-> 双向迭代器
-> 随机访问迭代器
右箭头表示“可被替代为”。例如,为输出迭代器调用的任何算法应该都非常适合向前迭代器,而不是相反。
若要对序列进行只读访问,可以使用以下任何项:
输入迭代器
-> 向前迭代器
-> 双向迭代器
-> 随机访问迭代器
输入迭代器在这种情况下是所有类别中最弱的。
最后,若要对序列进行读/写访问,可以使用以下任何项:
向前迭代器
-> 双向迭代器
-> 随机访问迭代器
对象指针可以始终充当随机访问迭代器,因此如果它支持对它指定的序列进行正确的读/写访问,则它可以充当任何类别的迭代器。
对象指针以外的迭代器 Iterator
还必须定义专用化 iterator_traits<Iterator>
所需的成员类型。 可通过从公共基类 iterator 派生 Iterator
来满足这些需求。
请务必了解每个迭代器类别的承诺和限制,查看 C++ 标准库中的容器和算法如何使用迭代器。
注意
可以使用范围 for 循环来避免显式使用迭代器。 有关详细信息,请参阅基于范围的 for 语句。
Microsoft C++ 现在提供经过检查的迭代器和调试迭代器,以确保不会覆盖容器的边界。 有关详细信息,请参阅经过检查的迭代器和调试迭代器支持。