Menu
Coddy logo textTech

イテレータ

CoddyのC++ジャーニー「オブジェクト指向プログラミング」セクションの一部 — レッスン 72/104。

イテレータは、コンテナとアルゴリズムの間の架け橋として機能するオブジェクトです。これらは、コンテナが内部でどのようにデータを保持しているかに関わらず、あらゆるコンテナ内の要素にアクセスするための統一された方法を提供します。イテレータは、コンテナ内を移動する方法を知っている汎用化されたポインタであると考えてください。

すべてのSTLコンテナはbegin()メソッドとend()メソッドを提供しています。begin()イテレータは最初の要素を指し、end()は最後の要素の次、つまり停止位置を示す番兵(センチネル)を指します:

#include <vector>
#include <iostream>

int main() {
    std::vector<int> nums = {10, 20, 30};
    
    for (std::vector<int>::iterator it = nums.begin(); it != nums.end(); ++it) {
        std::cout << *it << " ";  // デリファレンスして値を取得する
    }
    // 出力: 10 20 30
}

autoキーワードは、イテレータの宣言を大幅に簡素化します:

for (auto it = nums.begin(); it != nums.end(); ++it) {
    *it *= 2;  // イテレータを介して要素を変更する
}
// nums は現在 {20, 40, 60} です

イテレータは、その機能に基づいてさまざまなカテゴリに分類されます。ランダムアクセスイテレータvectorのものなど)は、it + 3it1 - it2などの算術演算をサポートしています。

双方向イテレータ (list, map など) は、++-- を使用して前方および後方に移動できます。前方向イテレータは、一方向にのみ移動できます。

逆方向に走査するには、rbegin()rend() を使用します:

for (auto rit = nums.rbegin(); rit != nums.rend(); ++rit) {
    std::cout << *rit << " ";  // 逆順に出力します
}
challenge icon

チャレンジ

簡単

イテレータを使用してアイテムのコレクションを走査および操作する、在庫追跡システムを構築しましょう。さまざまな種類のイテレータを使用して、さまざまな方法でデータをナビゲートする練習をします。

コードは2つのファイルに分けて構成します:

  • Inventory.h: std::vector<int> に格納されたアイテム数量のコレクションを管理する Inventory クラスを定義します。

    クラスには以下のメソッドを用意する必要があります:

    • addItem(int quantity) — 在庫にアイテムの数量を追加します
    • printForward()begin()end() を持つイテレータを使用して、すべての数量をスペースで区切って表示し、最後に改行を出力します
    • printReverse()rbegin()rend() を持つリバースイテレータを使用して、すべての数量を逆順にスペースで区切って表示し、最後に改行を出力します
    • doubleAll() — イテレータを使用してベクトルを走査し、各数量をその場で2倍にします
    • getTotal() — イテレータを使用して、すべての数量の合計を計算して返します

    コードを簡潔に保つために、イテレータの宣言には auto キーワードを使用してください。

  • main.cpp: アイテムの数量を表す4つの整数入力(それぞれ別の行)を読み取ります。

    Inventory オブジェクトを作成し、4つの数量すべてを追加します。次に、以下を行ってイテレータの使用例を示します:

    1. Forward: と出力し、続いて printForward() を呼び出す
    2. Reverse: と出力し、続いて printReverse() を呼び出す
    3. getTotal() を使用して Total: <sum> と出力する
    4. doubleAll() を呼び出して数量を修正する
    5. After doubling: と出力し、続いて printForward() を呼び出す
    6. getTotal() を使用して New total: <sum> と出力する

例えば、入力が 10251530 の場合、出力は以下のようになります:

Forward: 10 25 15 30 
Reverse: 30 15 25 10 
Total: 80
After doubling: 20 50 30 60 
New total: 160

このチャレンジでは、イテレータを介した要素の読み取り(表示と合計の算出)と、イテレータを介した要素の修正(2倍にする処理)の両方を練習できます。また、リバースイテレータを使用することで、インデックス操作を行うことなく、いかに簡単に逆方向の走査ができるかを確認できます。

チートシート

イテレータは、コンテナ内の要素にアクセスするための統一された方法を提供するオブジェクトです。これらは、コンテナ内を移動する方法を知っている汎用的なポインタとして機能します。

すべてのSTLコンテナは、begin()メソッドとend()メソッドを提供します。begin()イテレータは最初の要素を指し、end()は最後の要素の次を指します。

std::vector<int> nums = {10, 20, 30};

for (std::vector<int>::iterator it = nums.begin(); it != nums.end(); ++it) {
    std::cout << *it << " ";  // デリファレンスして値を取得する
}

autoキーワードを使用して、イテレータの宣言を簡略化します。

for (auto it = nums.begin(); it != nums.end(); ++it) {
    *it *= 2;  // イテレータを介して要素を修正する
}

機能に基づいたイテレータのカテゴリ:

  • ランダムアクセスイテレータ(例:vector)は、it + 3it1 - it2のような算術演算をサポートします。
  • 双方向イテレータ(例:listmap)は、++--を使用して前後方向に移動できます。
  • 前方イテレータは、一方向にのみ移動できます。

逆方向の走査には、rbegin()rend()を使用します。

for (auto rit = nums.rbegin(); rit != nums.rend(); ++rit) {
    std::cout << *rit << " ";  // 逆順に表示する
}

自分で試してみよう

#include <iostream>
#include "Inventory.h"

using namespace std;

int main() {
    // 4つの整数の入力を読み込む
    int q1, q2, q3, q4;
    cin >> q1;
    cin >> q2;
    cin >> q3;
    cin >> q4;

    // TODO: Inventory オブジェクトを作成する

    // TODO: 4つの数量すべてを在庫(inventory)に追加する

    // TODO: "Forward: " と出力し、その後に printForward() を呼び出す

    // TODO: "Reverse: " と出力し、その後に printReverse() を呼び出す

    // TODO: "Total: " と出力し、その後に getTotal() の結果を出力する

    // TODO: doubleAll() を呼び出して数量を変更する

    // TODO: "After doubling: " と出力し、その後に printForward() を呼び出す

    // TODO: "New total: " と出力し、その後に getTotal() の結果を出力する

    return 0;
}
quiz icon腕試し

このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。

オブジェクト指向プログラミングのすべてのレッスン