C++初学者指南-5.标准库(第一部分)–迭代器 Iterators
文章目录
- 指向某个位置的对象
- 可能指向一个可读的内存地址或对象
- 以一种与数据布局无关的方式迭代容器元素
- 也用于指定容器中的位置和范围(用于插入、删除等操作)
在接下来的章节中,符号 @name 将被用来表示一个迭代器对象/参数/返回值。请注意,@ 在C++中既不是允许的操作符,也没有其他意义。
1.默认正向迭代器
可从标准容器中获取
具有成员函数:
- container.begin() → @第一个元素
- container.end() → @最后一个元素之后
或者用独立的函数:(C++11)
- std::begin(container) → @第一个元素
- std::end(container) → @最后一个元素之后
迭代器指的是容器中的一个位置:
vector<int> v {1,2,3,4,5,6,7};
auto i = begin(v);
auto e = end(v);
执行示例代码
*i 获取在位置i处的元素
cout << *i; | prints 1 |
cout << *(i+2); | prints 3 |
cout << *e; | 未定义行为 |
结束迭代器仅用作位置指示器,不应该用来访问元素。
++i | 向结束位置前进一步(一个元素位置) |
–i | 向开始位置后退一步(一个元素位置) |
i += 2 | 向结束位置前进两步(两个元素位置) |
i -= 3 | 向开始位置后退三步(三个元素位置) |
2.反向迭代器
许多(但不是所有)标准容器中可获得
使用容器成员函数:
- container.rbegin() → @最后一个元素
- container.rend() → @第一个元素之前
或者用独立的函数:(C++11)
- std::rbegin(container) → @最后一个元素
- std::rend(container) → @第一个元素之前
反向迭代器指的是容器中的一个位置:
vector<int> v {1,2,3,4,5,6,7};
auto i = rbegin(v);
auto e = rend(v);
运行示例代码
*i 获取在位置i处的元素
cout << *i; | prints 7 |
cout << *(i+2); | prints 5 |
cout << *e; | 未定义行为 |
rend迭代器仅用于作为位置指示器,不应该用来访问元素。
++i | 向开始位置后退一步(一个元素位置) |
–i | 向结束位置前进一步(一个元素位置) |
i += 2 | 向开始位置后退两步(两个元素位置) |
i -= 3 | 向结束位置前进三步(三个元素位置) |
ri.base()从反向迭代器返回相应的普通(非反向)迭代器。
反向迭代器 = 正常位置 - 1
正常位置 = 反向迭代器 + 1
vector<int> v {1,2,3};
auto re = rbegin(v);
auto fw = re.base();
注意,当反向迭代器指向元素3的时候,它的普通迭代器的位置是元素3后面的位置即正向迭代器的 end()。
3.基于迭代器的循环
前向方向
- 适用于所有标准序列容器
- 可能存在越界访问错误
- 繁琐
std::vector<int> v {1, 2, 3, 4, 5, 6};
for (auto i = begin(v); i != end(v); ++i) { cout << *i; }
反向方向
- 适用于所有双向容器
- 可能存在越界访问错误
- 繁琐
std::vector<int> v {1, 2, 3, 4, 5, 6};
for (auto i = rbegin(v); i != rend(v); ++i) { cout << *i; }
4.示例:交换相邻的一对元素
void swap_adjacent_pairs (std::vector<int>& v) {
if (v.size() < 2) return;
for (auto i=begin(v), j=i+1, e=end(v); j < e; i+=2, j+=2) {
std::swap(*i,*j);
}
}
vector<int> v {1,2,3,4,5,6};
swap_adjacent_pairs(v);
5.迭代器范围
= p和q这对迭代器
范围末端迭代器 q 指向最后一个元素后面的位置(意思是迭代器范围对中的末端迭代器只是指示位置,此元素不包含在范围内)
用于指定元素范围
- 从容器中删除元素
std::vector v {1,2,3,4,5,6,7,8,9};
v.erase(begin(v)+3, begin(v)+6);
- 向容器中插入元素
- 分配给另一个容器
- 由标准算法处理
- …
6.迭代器范围中的元素数量
distance(@range_begin, @element_in_range) → 元素在范围内的个数
函数参考
#include <vector>
#include <iostream>
#include <algorithm>
#include <iterator> // std::distance
std::vector<int> v {0,1,2,3,4,5,6,7,8};
// size of subrange (as shown in image)
auto n = distance(begin(v)+2, begin(v)+7); // int n = 5
// size of entire container
auto m = distance(begin(v), end(v)); // int m = 9
std::vector<int> w {4,5,1,9,8};
// get index of smallest element in w:
auto argmin = distance(begin(w), min_element(begin(w),end(w)) );
// int argmin = 2
避免在像 std::list 这样的非随机访问容器中使用迭代器的距离,因为运行时间将与输入范围的大小成正比!
7. 总结:迭代器
指向容器/内存中的位置:
不要对end()位置用解引用符 * 访问!
仅仅把end()当成特殊位置
相关内容
查看 C++ 反向迭代器的另一种方式
附上原文链接
如果文章对您有用,请随手点个赞,谢谢!^_^