Bootstrap

C++初学者指南-5.标准库(第一部分)--迭代器

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++ 反向迭代器的另一种方式

附上原文链接
如果文章对您有用,请随手点个赞,谢谢!^_^

;