HOWTO · C++

C++ で配列サイズを求める方法

この記事では、配列の長さを求める方法を示します。

このページの内容

C++ で配列の長さを知るには、要素数を数えます。適切な方法は型によって異なります。宣言されたスコープ内にある組み込み配列には sizeof、std::array や std::vector には size()、標準ライブラリの汎用関数を使う場合は std::size が使えます。範囲をすでに反復できるなら、範囲ベースの for ループで要素数を数えることもできます。

範囲ベースの for ループで C++ の配列要素を数える

範囲ベースの for ループは、配列やその他の反復可能な範囲に含まれる各要素を順に処理します。要素を数えるには、各要素を処理するたびにカウンターを1増やします。

#include <iostream>

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

    for (int value : values) {
        (void)value;
        ++count;
    }

    std::cout << "Element count: " << count << '\n';
}

この方法で数えられるのは、values が提供する範囲の要素です。生のポインターや動的に確保した領域のサイズを調べることはできません。その場合は要素数を別に保持するか、サイズを取得できるコンテナーを使いましょう。

sizeof で組み込み配列の長さを調べる

現在のスコープで配列のままである組み込み配列では、配列全体のバイト数を1要素分のバイト数で割ると要素数を求められます。

#include <iostream>
#include <cstddef>

int main() {
    int values[] = {1, 2, 3, 4, 5};
    const std::size_t count = sizeof(values) / sizeof(values[0]);

    std::cout << "Element count: " << count << '\n';
}

sizeof(values) は配列全体が占めるバイト数を返し、sizeof(values[0]) は1要素が占めるバイト数を返します。その商が要素数です。この例では std::size_t を使うために <cstddef> をインクルードしています。

配列を関数に渡すと、この計算で要素数を求めることはできなくなります。int values[] と書かれた仮引数は int* values に調整されます。その関数内での sizeof(values) が測るのは元の配列ではなくポインターです。計算結果はポインターと要素のサイズに依存するため、移植可能な要素数にはなりません。要素数を別の引数として渡すか、代わりにコンテナーを受け取るようにしてください。

std::array と std::vector では size() を使う

std::array と std::vector はどちらも、要素数を返すメンバー関数 size() を備えています。std::array は要素数が固定された配列を表し、std::vector は要素の追加や削除に応じてサイズが変わります。

#include <array>
#include <iostream>
#include <vector>

int main() {
    std::array<int, 3> fixed{4, 8, 12};
    std::vector<int> resizable{5, 10, 15, 20};

    std::cout << "std::array: " << fixed.size() << '\n';
    std::cout << "std::vector: " << resizable.size() << '\n';
}

使用しているコンテナーに対応するメンバー関数を使いましょう。std::array::size() は固定された要素数を返し、std::vector::size() は現在のベクターの要素数を返します。

std::end() と std::begin() で配列の長さを調べる

組み込み配列では、std::begin は最初の要素を指し、std::end は最後の要素の次の位置を指します。この2つのポインターを引くと、その間にある要素の数が得られます。これらの関数を使うには <iterator> をインクルードします。

#include <iostream>
#include <iterator>

int main() {
    int values[] = {2, 4, 6, 8};
    const auto count = std::end(values) - std::begin(values);

    std::cout << "Element count: " << count << '\n';
}

どちらのポインターも同じ配列内、または配列の末尾の次の位置を指すため、この減算は有効です。組み込み配列を扱う場合に便利ですが、std::array や std::vector では通常、メンバー関数 size() のほうが分かりやすいでしょう。

std::size() で要素数を取得する

std::size は要素数を返す標準ライブラリ関数です。組み込み配列のほか、std::array や std::vector などの標準コンテナーで使えます。使用するには <iterator> をインクルードします。

#include <array>
#include <iostream>
#include <iterator>
#include <vector>

int main() {
    int built_in[] = {3, 6, 9};
    std::array<int, 2> fixed{7, 14};
    std::vector<int> resizable{11, 22, 33, 44};

    std::cout << "Built-in array: " << std::size(built_in) << '\n';
    std::cout << "std::array: " << std::size(fixed) << '\n';
    std::cout << "std::vector: " << std::size(resizable) << '\n';
}

メンバー関数の size() と異なり、std::size(container) は独立した関数を呼び出します。対応する配列やコンテナーに同じ書き方を使えますが、各コンテナーが備える size() メンバー関数も引き続き使えます。

配列の型に合った方法を選ぶ

  • 宣言されたスコープ内にある組み込み配列には、sizeof(array) / sizeof(array[0]) または std::size(array) を使います。
  • std::array と std::vector には、それぞれの size() メンバー関数を使うのがおすすめです。共通の関数呼び出しが便利なら std::size(container) を使えます。
  • イテレーターの減算が周囲のコードに合う場合は、std::end(array) - std::begin(array) を使います。
  • 反復可能な範囲の各要素を順に処理して数えたい場合は、範囲ベースの for ループを使います。
  • ポインターや動的に確保した配列では、要素数を別に保持するか、コンテナーを使います。ポインターだけでは、確保領域の要素数は分かりません。

大切なのは、バイト単位の記憶領域のサイズと要素数を区別することです。sizeof が測るのはバイト数です。要素1つ分のバイト数で割って要素数を求められるのは、式が配列全体を参照している間だけです。コンテナーのサイズ関数とイテレーターの減算は、要素数を直接返します。