迭代器
与容器一样,迭代器有着公共的接口: 如果一个迭代器提供某个操作,那么所有提供相同操作的迭代器对这个操作的实现方式都是相同的。
例如,标准容器类型上的所有迭代器都允许我们访问容器中的元素,而所有迭代器都是通过解引用运算符来实现这个操作的。
类似的,标准库容器的所有迭代器都定义了递增运算符,从当前元素移动到下一个元素。
表3.6列出了容器迭代器支持的所有操作,其中有一个例外不符合公共接口特点——forward_list迭代器不支持递减运算符(--)。表3.7列出了迭代器支持的算术运算,这些运算只能应用于string、vector、deque和array的迭代器。我们不能将它们用于其他任何容器类型的迭代器。
迭代器范围
一个迭代器范围(iterator range)由一对迭代器表示,两个迭代器分别指向同一个容器中的元素或者是尾元素之后的位置(one past the last element)。这两个迭代器通常被称为begin和end,或者是 first和last(可能有些误导),它们标记了容器中元素的一个范围。
虽然第二个迭代器常常被称为 last,但这种叫法有些误导,因为第二个迭代器从来都不会指向范围中的最后一个元素,而是指向尾元素之后的位置。迭代器范围中的元素包含 first 所表示的元素以及从first开始直至last(但不包含last)之间的所有元素。
这种元素范围被称为左闭合区间(left-inclusive interval),其标准数学描述为[begin, end)
表示范围自begin开始,于end之前结束。迭代器begin和end必须指向相同的容器。 end可以与begin指向相同的位置,但不能指向begin之前的位置。
标准库使用左闭合范围是因为这种范围有三种方便的性质。假定 begin和end构成一个合法的迭代器范围,则
- 如果 begin 与end相等,则范围为空
- 如果 begin与end 不等,则范围至少包含一个元素,且begin指向该范围中的第一个元素
- 我们可以对 begin 递增若干次,使得 begin==end这些性质意味着我们可以像下面的代码一样用一个循环来处理一个元素范围,而这是安全的∶
while (begin != end){
*begin = val; // 正确:范围非空,因此begin指向一个元素
++begin; // 移动迭代器,获取下一个元素
}
给定构成一个合法范围的迭代器begin 和end,若begin=end,则范围为空。在此情况下,我们应该退出循环。如果范围不为空,begin指向此非空范围的一个元素。因此,在 while循环体中,可以安全地解引用 begin,因为 begin必然指向一个元素。最后,由于每次循环对 begin 递增一次,我们确定循环最终会结束。