C++で配列のサイズを取得する7つの方法

C++で配列のサイズを取得する方法を説明する図解C++
この記事は約12分で読めます。

 

【サイト内のコードはご自由に個人利用・商用利用いただけます】

この記事では、プログラムの基礎知識を前提に話を進めています。

説明のためのコードや、サンプルコードもありますので、もちろん初心者でも理解できるように表現してあります。

基本的な知識があればカスタムコードを使って機能追加、目的を達成できるように作ってあります。

※この記事は、一般的にプロフェッショナルの指標とされる『実務経験10,000時間以上』を凌駕する現役のプログラマチームによって監修されています。

サイト内のコードを共有する場合は、参照元として引用して下さいますと幸いです

※Japanシーモアは、常に解説内容のわかりやすさや記事の品質に注力しております。不具合、分かりにくい説明や不適切な表現、動かないコードなど気になることがございましたら、記事の品質向上の為にお問い合わせフォームにてご共有いただけますと幸いです。
(送信された情報は、プライバシーポリシーのもと、厳正に取扱い、処分させていただきます。)

はじめに

C++でのプログラミングにおいて、配列は基本的かつ重要な要素です。

この記事を読むことで、初心者から上級者まで、C++における配列のサイズを取得する方法を理解し、実践できるようになるでしょう。

配列のサイズを取得することは、配列を扱う上で不可欠なスキルであり、様々なプログラミングシナリオで役立ちます。

この記事では、配列の基本から、配列のサイズを効率的に取得するさまざまな方法までを、分かりやすく解説していきます。

●C++と配列の基本

C++における配列は、同一型の要素を一定の順序で格納するデータ構造です。

配列は、複数のデータを一つの名前で管理し、インデックスを使って各要素にアクセスできます。

C++では、静的配列と動的配列の二つの主な種類があります。

静的配列は、コンパイル時にサイズが固定され、動的配列はプログラム実行時にサイズが変更できるという特徴があります。

配列のサイズを正確に理解することは、オーバーフローやアンダーフローのようなエラーを防ぐ上で重要です。

○配列とは

配列は、同じ型の複数の要素を連続したメモリ領域に格納するデータ構造です。

例えば、int型の配列は複数のint型の値を一つの連続したメモリブロックに保存します。

これにより、インデックスを使って配列の特定の要素に効率的にアクセスすることが可能になります。

配列は、ループ処理やデータ管理など、様々な場面で活用されます。

○C++における配列の特徴

C++における配列は、固定長と動的長の二つに大別されます。固定長配列(静的配列)は、コンパイル時にそのサイズが決定されます。

例えば、int arr[10]; と宣言すると、10個の整数を格納できる配列が作成されます。

一方、動的配列(例:std::vector)は、プログラム実行時にサイズが変更可能です。

動的配列は柔軟性が高く、実行時にデータの量に応じてサイズを調整できるため、多くの場合で有用です。

ただし、動的配列の管理には注意が必要で、特にメモリ管理におけるリークやオーバーフローのリスクに留意する必要があります。

●配列のサイズを取得する方法

C++において配列のサイズを取得する方法は複数存在します。これらの方法を理解することは、配列を効率的に扱う上で非常に重要です。

特に、配列のサイズがプログラムの動作に直接影響する場合、正確なサイズの取得は不可欠です。

ここでは、静的配列、動的配列、そしてstd::arrayを使ったサイズ取得の方法を詳細に解説します。

○サンプルコード1:静的配列のサイズ取得

静的配列のサイズは、配列の全体のサイズをその要素のサイズで割ることによって取得できます。

例えば、int型の要素を10個持つ配列の場合、下記のようにしてサイズを取得します。

#include <iostream>
using namespace std;

int main() {
    int arr[10];
    int size = sizeof(arr) / sizeof(arr[0]);
    cout << "配列のサイズ: " << size << endl;
    return 0;
}

このコードでは、sizeof(arr)で配列arrの全体のサイズを取得し、sizeof(arr[0])で配列の一つの要素のサイズを取得しています。

これらを割ることで、配列の要素数、つまり配列のサイズを求めています。

○サンプルコード2:動的配列のサイズ取得

動的配列、例えばstd::vectorを使用する場合、サイズの取得はより簡単です。

std::vectorにはsize()メソッドが用意されており、これを使ってサイズを取得できます。

#include <iostream>
#include <vector>
using namespace std;

int main() {
    vector<int> v = {1, 2, 3, 4, 5};
    cout << "動的配列のサイズ: " << v.size() << endl;
    return 0;
}

この例では、std::vector<int>型の動的配列vを作成し、v.size()でそのサイズを取得しています。

○サンプルコード3:std::arrayを使ったサイズ取得

std::arrayを使用する場合、サイズの取得はさらに容易です。

std::arrayは、サイズを型の一部として持っているため、size()メソッドを使って直接サイズを取得できます。

#include <iostream>
#include <array>
using namespace std;

int main() {
    array<int, 5> arr = {1, 2, 3, 4, 5};
    cout << "std::arrayのサイズ: " << arr.size() << endl;
    return 0;
}

このコードでは、std::array<int, 5>型の配列arrを作成し、arr.size()でサイズを取得しています。

std::arrayはコンパイル時にサイズが決定されるため、この方法は非常に信頼性が高いです。

○サンプルコード4:std::vectorを使ったサイズ取得

C++の標準テンプレートライブラリに含まれるstd::vectorは、動的配列の一形態です。

std::vectorを使用すると、要素の追加や削除に伴って自動的に配列のサイズが調整されます。

std::vectorのサイズを取得するには、size()メソッドを使用します。

#include <iostream>
#include <vector>
using namespace std;

int main() {
    vector<int> vec = {10, 20, 30, 40, 50};
    cout << "vectorのサイズ: " << vec.size() << endl;
    return 0;
}

このコードでは、std::vector<int>型のオブジェクトvecを宣言し、初期化しています。

vec.size()を呼び出すことで、vecが現在持っている要素の数、つまり配列のサイズを取得しています。

○サンプルコード5:関数テンプレートを使った汎用的なサイズ取得

C++で配列やコンテナのサイズを取得する汎用的な方法として、関数テンプレートを使用する方法があります。

この方法は、さまざまな型の配列やコンテナに対して一つの関数でサイズを取得できる柔軟性を持っています。

下記のサンプルコードでは、テンプレートを使ったサイズ取得関数を定義し、それを使って配列とstd::vectorのサイズを取得しています。

#include <iostream>
#include <vector>
using namespace std;

template <typename T, unsigned S>
unsigned arraySize(const T (&)[S]) {
    return S;
}

int main() {
    int arr[] = {1, 2, 3, 4, 5};
    vector<int> vec = {1, 2, 3, 4, 5};

    cout << "配列のサイズ: " << arraySize(arr) << endl;
    cout << "vectorのサイズ: " << vec.size() << endl;
    return 0;
}

このコードのarraySize関数は、配列の参照とそのサイズをテンプレートパラメータとして受け取り、配列のサイズを返します。

これにより、配列のサイズを取得する際に、sizeofを直接使う手間を省くことができます。

また、std::vectorの場合は通常通りsize()メソッドを使用します。

●配列のサイズ取得の応用例

配列のサイズを知ることは、多くのプログラミングシナリオで重要な役割を果たします。

配列のサイズに基づくループ処理や、条件に応じた配列のリサイズなど、サイズ取得の応用例は多岐にわたります。

これらの応用例を理解することで、C++プログラミングの幅が広がります。

○サンプルコード6:配列サイズに基づくループ処理

配列のサイズを取得することで、そのサイズに基づいてループ処理を行うことができます。

下記のサンプルコードでは、配列の要素をすべて出力する簡単な例を表しています。

#include <iostream>
using namespace std;

int main() {
    int arr[] = {1, 2, 3, 4, 5};
    int size = sizeof(arr) / sizeof(arr[0]);

    for (int i = 0; i < size; ++i) {
        cout << arr[i] << " ";
    }
    cout << endl;

    return 0;
}

このコードでは、配列arrのサイズを取得し、そのサイズに基づいてforループを実行しています。

これにより、配列のすべての要素を順に出力することができます。

○サンプルコード7:条件に応じた配列のリサイズ

std::vectorを使用する場合、プログラムの実行中に配列のサイズを動的に変更することが可能です。

例えば、ある条件に基づいて配列のサイズを拡大または縮小することができます。

#include <iostream>
#include <vector>
using namespace std;

int main() {
    vector<int> vec = {1, 2, 3, 4, 5};

    // 条件に応じてサイズを変更
    if (vec.size() < 10) {
        vec.resize(10, 0); // サイズを10に拡大し、新しい要素は0で初期化
    }

    for (int val : vec) {
        cout << val << " ";
    }
    cout << endl;

    return 0;
}

このコードでは、std::vectorresizeメソッドを使用して、配列のサイズを条件に応じて変更しています。

この例では、vecのサイズが10未満の場合、サイズを10に拡大し、新しく追加された要素を0で初期化しています。

●注意点と対処法

C++における配列のサイズ取得にはいくつかの注意点があります。

これらを理解し、適切に対処することで、プログラムのバグや予期せぬ動作を防ぐことができます。

○配列のサイズを誤って取得するリスク

配列のサイズを誤って取得すると、配列の範囲外のメモリにアクセスしたり、配列が持っていない要素を参照しようとしたりする可能性があります。

これは、配列のオーバーフローやアンダーフローの原因となり、プログラムのクラッシュや予期せぬ動作を引き起こす可能性があります。

特に、静的配列のサイズをsizeof演算子を使って取得する場合は、配列がポインタとして渡されたときには正しいサイズを返さないことに注意が必要です。

動的配列の場合、std::vectorなどのコンテナを使用することで、サイズ取得の正確さを保証できます。

○メモリリークの防止

動的配列や動的に確保したメモリの使用では、メモリリークに特に注意する必要があります。

動的配列やポインタを使用してメモリを確保した場合は、そのメモリを適切に解放することが重要です。

C++11以降では、スマートポインタ(std::unique_ptrstd::shared_ptrなど)を使用することで、自動的にメモリの管理を行い、メモリリークのリスクを減らすことができます。

スマートポインタは、ポインタがスコープを抜けるときに自動的にメモリを解放するため、手動での解放を忘れるリスクを減らすことができます。

●カスタマイズ方法

C++における配列操作は、基本的な機能に加えて、カスタマイズを行うことでさらに効率的かつ強力になります。

特に、特定の処理を繰り返し使用する場合、カスタム関数を作成することでコードの再利用性と可読性を高めることができます。

○配列操作のカスタム関数作成

配列操作に関する一般的な処理をカスタム関数として定義することで、コードの簡潔化と効率化を図ることができます。

例えば、配列の要素を表示する関数や、配列の特定の要素に対する操作を行う関数などが考えられます。

#include <iostream>
using namespace std;

void printArray(const int arr[], int size) {
    for (int i = 0; i < size; ++i) {
        cout << arr[i] << " ";
    }
    cout << endl;
}

int main() {
    int myArray[] = {1, 2, 3, 4, 5};
    int size = sizeof(myArray) / sizeof(myArray[0]);

    printArray(myArray, size);

    return 0;
}

このコードでは、printArray関数は配列とそのサイズを引数として受け取り、配列の要素を順に表示します。

このように関数を定義することで、配列の表示処理を再利用しやすくなります。

○効率的な配列処理のテクニック

配列を効率的に処理するためには、適切なデータ構造の選択やアルゴリズムの使用が重要です。

例えば、頻繁に要素の挿入や削除を行う場合は、std::vectorstd::listのような動的配列を使用することが効果的です。

また、要素の検索やソートなどの操作には、C++の標準ライブラリに含まれるアルゴリズム関数を利用することが推奨されます。

C++には<algorithm>ヘッダーに多くの便利なアルゴリズム関数が用意されており、これらを活用することで、効率的かつ簡潔に配列処理を実装することができます。

例えば、std::sort関数を使って配列をソートする、std::find関数を使って特定の要素を検索するなど、多様な処理を効率的に行うことができます。

まとめ

この記事では、C++における配列のサイズを取得するさまざまな方法を詳しく解説しました。

静的配列から動的配列、標準テンプレートライブラリを使用した方法まで、各手法の特徴と使用例を紹介しました。

さらに、配列操作をカスタマイズする方法とその効率的な処理テクニックも紹介しました。

これらの知識を身につけることで、C++プログラミングにおける配列の取り扱いがより柔軟かつ効率的になるでしょう。

初心者から上級者まで、この記事がC++における配列操作の理解に役立つことを願っています。