本文へスキップ
BecomeCoder

C++コース · 第14章 STLコンテナ ― 標準の入れ物を使いこなす · レッスン59

イテレータ ― コンテナを横断する共通の仕組み

ブラウザで完結

導入

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;
}

inserterase が位置をイテレータで指定していたのも、この共通の仕組みのおかげです。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 やアルゴリズムはすべてこの仕組みの上に成り立っています。

実際に動かしてみよう

下のエディタにC++を書いて「コンパイル & 実行」を押すと、ブラウザ内で本物のC++コンパイラ(clang + libc++)がその場でコンパイルして実行し、出力が表示されます。std::string・vector・クラス・テンプレート・STL などモダンC++がそのまま動きます。本文の例を書き換えて試しながら進めましょう(初回だけコンパイラの読み込みに時間がかかります。以降はキャッシュされます。この回は標準入力(cin)は使わず、値はコードに直接書きます)。

C/C++ — ブラウザ内で本物のコンパイラで実行

ブラウザ内で本物のC/C++コンパイラ(clang + libc++ / WebAssembly)を動かします。構造体・malloc/free・std::string・vector・クラス・テンプレート・STL などがそのまま実行できます(初回のみコンパイラの読み込みに時間がかかります。以降はブラウザにキャッシュされます)。
スクロールして表示された時点でも自動で読み込まれます。