type
status
date
slug
summary
tags
category
icon
password
Property
可以使用下标运算符来访问
string
对象的字符或vector
对象的元素,还有另外一种更通用的机制也可以实现同样的目的,这就是迭代器(iterator)。在
C++
中更常用的访问容器中的元素方式是通过迭代器,因为有些容器无法通过下标来访问的,这种容器是不可随机访问的。所有容器都可以通过迭代器来访问元素。虽然string
不是容器,但是string
支持很多容器的操作,包括迭代器和下标访问。迭代器是对语言中的指针的一种抽象和模拟,用来间接访问元素。与指针一样,通过迭代器可以从一个元素移动到另一个元素,可以通过解引用返回元素的引用,可以通过箭头符调用其成员函数。迭代器也有非法迭代器(invalid iterator),只有确实指向元素或者指向尾元素的下一个位置才是合法迭代器,其它所有迭代器都是非法的。
迭代器
和指针不一样的是,获取迭代器不是使用取地址符,有迭代器的类型同时拥有返回迭代器的成员。比如,这些类型都拥有名为
begin
和end
的成员:begin
成员负责返回指向第一个元素(或第一个字符)的迭代器
end
成员则负责返回指向容器(或string
对象)“尾元素的下一位置”的迭代器,指示的是容器的一个本不存在的“尾后”元素。这样的迭代器没什么实际含义,仅是个标记而已,表示已经处理完了容器中的所有元素。
end
成员返回的迭代器通常被称作尾后迭代器或者简称为尾迭代器。如果容器为空,则begin
和end
返回的是同一个迭代器,都是尾后迭代器。迭代器运算符
迭代器只支持比较少的操作,只有支持随机访问的容器支持其迭代器与整数的加减法来用快速步进迭代器,以下是所有迭代器都支持的操作:
*iter
解引用迭代器,返回所指向的元素的引用,不能对尾后迭代器进行解引用。解引用一个非法迭代器和尾后迭代器的行为是未定义的
iter->mem
直接调用迭代器所指向元素的成员函数mem
,与(*iter).mem
完全一致
++iter
自增,使其指向下一个元素,不应该对尾后迭代器进行自增操作
--iter
自减,使其指向前一个元素
iter1 == iter2
判断两个迭代器是否相等,只有指向同一个容器中的同一个元素(尾后元素也是一个元素)的迭代器才会相等
iter1 != iter2
判断两个迭代器不相等
C++
常用的比较迭代器的方式是 !=
而不是<
,其原因在于很多迭代器根本没有<
操作,为了支持所有迭代器,通用的做法是用!=
来比较:迭代器类型
通常不知道也不需要知道迭代器的确切类型,标准库为每个容器类定义两个迭代器
iterator
和 const_iterator
。所有的
const
对象返回的的迭代器都是const_iterator
,const
迭代器和const
指针一样不能用于改变所指向的元素值。非const
对象可以通过cbegin
和cend
成员函数返回const
迭代器。迭代器是一组概念相关的类型,它们都支持一类操作,并且行为是类似的。同样容器也是一组相关的类型。
begin和end运算符
begin
和 end
返回的迭代器具体类型由对象是否是常量决定,如果对象是常量,则返回 const_iterator
;如果对象不是常量,则返回 iterator
C++11
新增了cbegin
和cend
函数,不论vector
或string
对象是否为常量,都返回const_iterator
迭代器某些对vector对象的操作会使迭代器失效
不能在范围for循环中向
vector
对象添加元素。任何可能改变容器对象容量的操作(如push_back
)会使得之前返回的迭代器失效。所以,不要在使用迭代器的循环中改变vector
的长度。结合解引用和成员访问
解引用迭代器可获得迭代器所指的对象,如果该对象的类型恰好是类,可以进一步访问它的成员。例如, 一个由字符串组成
vector
对象,想检查其元素是否为空,令it
是该vector
对象的迭代器, 检查it
所指字符串是否为空:为了简化表达式,
C++
定义了箭头运算符->
,把解引用和成员访问两个操作结合在一起,iter>mem
与(*iter).mem
完全一致:迭代器算术运算
只有少部分容器支持迭代器的算术运算,支持算术运算的容器通常是可随机访问的容器,意思是可以在任何时刻访问容器中的任意元素,而其它容器则必须一个一个向前移动访问。这种区别就跟数组与链表的区别。
迭代器算术运算指的是对迭代器加减整数返回的是一个跨越若干元素的另外一个迭代器,加则向后移动,减则向前移动。两个迭代器相减返回两者之间的距离。这样的迭代器通常还支持关系运算,可以比较大小,而其它的迭代器则不可以。
iter1 - iter2
的结果类型是各自容器的difference_type
,如:vector<int> difference_type
,这是一个有符号整数。使用迭代器完成了二分搜索: