1. 迭代器(iterator)可以指向 container(比如string, vector等)的任意一个成员,也可以向前或向后移动若干单位。所有的 library container 都有 iterator,但不一定支持下标操作,如 s[0]。所以用 iterator 来引用 container 内部成员,更具有一般性。
2. 使用 iterator
auto b = v.begin(), e = v.end();
其中 auto 表示 b 的类型自动定义;v.end() 指向 v 的最后一个元素之后的位置,称作 off-the-end iterator;v.begin() 指向 v 的第一个元素,或 off-the-end(如果 v 为空)。
也可以使用 const iterator,即只能读取指向对象,不能改变其值 v.cbegin(), v.cend();const 的 container 只有 const iterator,而普通的 container 既有 begin()/end() 也有 cbegin()/cend()。
3. dereference an iterator
string s("some string"); if (s.begin() != s.end()) { auto it = s.begin(); *it = toupper(*it); //第一个字母变大写 }
(*it) 表示迭代器 it 指向的单位。
4. 迭代器的操作
*iter 返回 iter 指向的元素的一个别名 iter->mem iter 指向元素的一个成员,也可写作 (*iter).mem ++iter iter 指向 container 的下一个单位,off-the-end itarator 不能被增加或dereference --iter iter 指向 container 的上一个单位 iter1 == iter2 指向同一个 container的同一个元素,或是同一个container的off-the-end iterator.
iter + n 向前移动 n 个元素
iter - n
iter += n
iter -= n
iter1 - iter 2 返回一个带符号的整数类型 difference_type,即 iter1, iter2 指向的元素之间相差的位置,iter2 加上这个整数就得到 iter1
>, >=, <, <=
注意:使用 iterator 时,不可改变 container 的 size,比如 vector 的 push_back 函数,使用时可能破坏它的所有 iterator。
5. 例子:在有序列表中做 binary search
auto beg = text.begin(), end = text.end(); auto mid = text.begin() + (end - beg)/2; while ( mid != end && *mid != sought){ if (sought < *mid) end = mid; else beg = mid +1; mid = beg + (end - beg)/2; }
寻找目标一直是 beg 到 end-1 指向的元素,如果 beg = end,mid = beg + (end-beg)/2 = end,说明 text 中不存在 sought。否则将在 (*mid) == sought 时结束寻找。所以运行完这块代码以后,要么 beg = mid = end,要么 (*mid) == sought。
while 循环运行的次数 k 满足 2^k = n,所以时间复杂度是 log(n)。