導入
vector でも map でも set でも、「先頭から末尾まで順にたどる」共通の方法があります。それが「イテレータ」です。範囲for の裏側で動いており、次章のアルゴリズムを使うために欠かせません。
説明
イテレータは「要素を指す印」で、ポインタに似た使い心地です。begin() が先頭、end() が「末尾の1つ後ろ(番兵)」を指し、++ で次へ進み、* で中身を取り出します。
flowchart LR b["begin()"] --> e1["要素0"] --> e2["要素1"] --> e3["要素2"] --> en["end()<br/>(末尾の1つ後ろ)"]
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<int> v = {10, 20, 30};
// イテレータで回す(範囲for はこれを簡潔にしたもの)
for (vector<int>::iterator it = v.begin(); it != v.end(); ++it) {
cout << *it << " "; // *it で中身を取り出す
}
cout << endl; // 10 20 30
auto it = v.begin(); // auto で書くのが実務では普通
++it; // 2番目へ
cout << *it << endl; // 20
return 0;
}
insert や erase が位置をイテレータで指定していたのも、この共通の仕組みのおかげです。find はイテレータを返し、見つからなければ end() を返します。
#include <iostream>
#include <vector>
#include <algorithm> // find
using namespace std;
int main() {
vector<int> v = {5, 10, 15};
auto it = find(v.begin(), v.end(), 10); // 10 を探す
if (it != v.end()) {
cout << "見つかった位置: " << (it - v.begin()) << endl; // 1
v.erase(it); // その位置を削除
}
for (int x : v) cout << x << " "; // 5 15
cout << endl;
return 0;
}
まとめ
イテレータは全コンテナ共通の「要素を指す印」で、begin()〜end() の範囲を ++ と * でたどります。end() は「末尾の次」を指す番兵です。範囲for やアルゴリズムはすべてこの仕組みの上に成り立っています。