HOWTO · C++

C++ で配列をループする方法

この記事では、C++ で配列を繰り返し処理する方法を示します。

このページの内容

配列には、同じ型の要素が一定の個数だけ格納されます。各要素を処理するには、インデックスが必要か、要素を変更するか、呼び出し可能オブジェクトを受け取るアルゴリズムを使うかに応じてループを選びます。以下の例はそれぞれ独立した配列と main を定義しているため、別々のプログラムとしてコンパイルできます。(C++)

インデックス付き for ループを使う

インデックス付きループでは、現在の位置を i で参照できます。3つの式は、インデックスの初期化、配列の範囲内かどうかの確認、各反復後のインデックス更新をそれぞれ行います。要素数が5個の配列で有効なインデックスは 0 から 4 までなので、比較には < count を使います。

次の例を実行します。

このセクションのコードと表示されるラベルや出力は英語のままです。

#include <iostream>

int main() {
    int values[] = {10, 20, 30, 40, 50};
    const int count = sizeof(values) / sizeof(values[0]);

    for (int i = 0; i < count; ++i) {
        std::cout << values[i] << ' ';
    }
    std::cout << '\n';
}
10 20 30 40 50

values がまだ配列である間は、sizeof 式で要素数を計算できます。配列を関数に渡すと、その関数内ではポインターとして扱われるため、要素数も別途渡すか、サイズを保持するコンテナーを使ってください。最後の要素を越えてアクセスしないよう、条件を要素数に合わせ、各反復で i を1回ずつ更新します。

while ループを使う

while ループは、単純な回数の確認よりも継続条件が複雑な場合に便利です。配列を走査するときは、ループの前にインデックスを初期化し、要素にアクセスする前に条件を確認してから、ループ本体の中でインデックスを更新します。更新を忘れると、ループが終了しないことがあります。

次の例を実行します。

このセクションのコードと表示されるラベルや出力は英語のままです。

#include <iostream>

int main() {
    int values[] = {5, 15, 25, 35};
    const int count = sizeof(values) / sizeof(values[0]);
    int i = 0;

    while (i < count) {
        std::cout << values[i] << ' ';
        ++i;
    }
    std::cout << '\n';
}
5 15 25 35

この方法では、インデックス順に要素を処理します。初期化、条件、更新をひとまとまりに扱いたい場合は for ループを使い、条件や更新がループ内の別の処理に左右される場合は while を使います。

範囲ベースの for ループを使う

範囲ベースのループは、インデックスを明示せずに各要素を直接処理します。通常の int value は要素のコピーであり、読み取りだけを行う小さな値に適しています。コピーを避けつつ要素を読み取り専用にするには const int& を使います。元の配列を変更する場合は int& を使います。

次の例を実行します。

このセクションのコードと表示されるラベルや出力は英語のままです。

#include <iostream>

int main() {
    int values[] = {1, 2, 3, 4, 5};

    for (const int& value : values) {
        std::cout << value << ' ';
    }
    std::cout << '\n';
}
1 2 3 4 5

たとえば、ループ変数を int& value にして value に値を代入すると、対応する配列要素が更新されます。位置を使わず、すべての要素を順に処理する場合に、この書き方は簡潔です。

std::for_each で配列を走査する

std::for_each はメソッドではなくアルゴリズムです。範囲の先頭と末尾の次を指すイテレーターに続けて、各要素に対して呼び出される呼び出し可能オブジェクトを受け取ります。このアルゴリズムには <algorithm> を、std::array には <array> をインクルードします。

次の例を実行します。

このセクションのコードと表示されるラベルや出力は英語のままです。

#include <algorithm>
#include <array>
#include <iostream>

int main() {
    std::array<int, 4> values = {2, 4, 6, 8};

    std::for_each(values.begin(), values.end(), [](int value) {
        std::cout << value * 2 << ' ';
    });
    std::cout << '\n';
}
4 8 12 16

この例ではラムダ式が呼び出し可能オブジェクトです。パラメーター int value は各要素をコピーします。呼び出し可能オブジェクトから配列を変更するには int& value を使います。begin() は最初の要素を指し、end() は最後の要素の次の位置を示すため、アルゴリズムに処理対象の範囲全体を渡せます。

用途に合わせてループを選ぶ

位置が必要な場合、隣接する要素を比較する場合、または位置の進め方を制御する場合は、インデックス付き for ループを使います。走査を終了する条件が別にある場合は while を使います。すべての要素に直接、読みやすくアクセスするには範囲ベースの for ループを選び、コピーの回避や値の変更が必要なら参照を使います。処理を呼び出し可能オブジェクトとして表す方法がアルゴリズム中心の設計に合う場合は std::for_each を使います。どの形式でも配列を走査できます。必要な情報と制御に応じて選び、インデックスでアクセスするときは配列の有効範囲を守ってください。