C++初學者指南-5.標準庫(第一部分)–迭代器 Iterators
文章目錄
- C++初學者指南-5.標準庫(第一部分)--迭代器 Iterators
- 1.默認正向迭代器
- 2.反向迭代器
- 3.基于迭代器的循環
- 4.示例:交換相鄰的一對元素
- 5.迭代器范圍
- 6.迭代器范圍中的元素數量
- 7. 總結:迭代器
- 指向某個位置的對象
- 可能指向一個可讀的內存地址或對象
- 以一種與數據布局無關的方式迭代容器元素
- 也用于指定容器中的位置和范圍(用于插入、刪除等操作)
在接下來的章節中,符號 @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++ 反向迭代器的另一種方式
附上原文鏈接
如果文章對您有用,請隨手點個贊,謝謝!^_^