【C++】STLのstd::arrayの使い方について詳しく解説

std::arrayは、固定長の配列を扱うためのコンテナです。

この記事では、初心者でもわかりやすくstd::arrayの使い方について詳しく解説します。

目次

std::arrayとは何か

std::arrayは、C++11から導入されたSTL(Standard Template Library)の一部であり、固定長の配列を表現するために使用されます。

std::arrayでは宣言時に要素数を指定し、その後変更することができません。

また、std::arrayは他のSTLコンテナと同様にイテレーターをサポートしており、範囲ベースのforループなどで簡単に要素を取り出すことができます。

例えば以下のように宣言します。

#include <array>

std::array<int, 5> arr = {1, 2, 3, 4, 5};

この場合、int型の要素を5つ持つ配列が作成されます。また、初期化子リストを使用して値を代入しています。初期化子リストは省略可能ですが、省略した場合は全て0で初期化されます。

std::arrayの宣言方法

C++のSTLに含まれるstd::arrayは、固定長の配列を扱うためのコンテナです。std::arrayを使用することで、配列のサイズを宣言時に指定し、その後変更することができなくなります。

std::arrayの宣言方法は以下のようになります。

#include <array>

std::array<int, 5> myArray; // int型要素を5つ持つ配列を宣言

上記の例では、int型要素を5つ持つ配列を宣言しています。<int, 5>は、int型要素を5つ持つ配列であることを示しています。また、myArrayはこの配列の名前です。

また、std::arrayは他のSTLコンテナ同様にイテレーターもサポートしており、以下のように使用することができます。

#include <iostream>
#include <array>

int main() {
    std::array<int, 3> myArray = {1, 2, 3};

    for (auto it = myArray.begin(); it != myArray.end(); ++it) {
        std::cout << *it << " ";
    }

    return 0;
}
1 2 3

上記の例では、イテレーターを使用してmyArray内の全ての要素を出力しています。

std::arrayの要素へのアクセス方法

std::arrayは、従来のC言語の配列の上位版とも言えるクラスであり、安全かつ簡単に配列を扱うことができます。

std::arrayの要素へのアクセス方法は、従来のC言語の配列と同様に、添字演算子[]を使用する方法を使えます。例えば、以下のようなstd::arrayがあった場合、

#include <array>

int main()
{
    std::array<int, 5> arr = {1, 2, 3, 4, 5};
    return 0;
}

arr[0]1arr[1]2arr[2]は3、arr[3]4arr[4]5となります。

また、at()関数を使用することでも要素へアクセスすることができます。at()関数では範囲外アクセス時に例外が発生するため、try-catchを使用することで安全性を高められます。

#include <array>
#include <iostream>

int main()
{
    std::array<int, 5> arr = {1, 2, 3, 4, 5};

    std::cout << arr.at(0) << std::endl; // 出力結果:1
    std::cout << arr.at(6) << std::endl; // 範囲外アクセス例外発生

    return 0;
}
1

また、普通の配列と同じようにループ処理することも可能です、

#include <array>
#include <iostream>

int main()
{
    std::array<int, 5> arr = { 1, 2, 3, 4, 5 };

    //要素数はsize()で取得可能
    for (int i = 0; i < arr.size(); i++) {
		std::cout << "arr[" << i << "] = " << arr[i] << std::endl;
    }

    //イテレーターを用いた以下の方法でもループ可能
    for (auto num : arr) {
        std::cout << num << " ";
    }
    return 0;
}
arr[0] = 1
arr[1] = 2
arr[2] = 3
arr[3] = 4
arr[4] = 5
1 2 3 4 5

以上がstd::arrayの要素へのアクセス方法です。

std::arrayの要素の追加・削除方法

std::arrayは、要素数が固定された配列を表現するためのSTLコンテナです。

そのため、std::arrayに要素を追加することはできません。また、既存の要素を削除することもできません。

ですが、std::arrayの要素を変更することは可能です。以下では、std::arrayの要素を変更する方法について説明します。

要素の変更方法

std::arrayの要素を変更するには、添字演算子[]を使用します。例えば、以下のようなコードで2番目の要素を3に変更することができます。

#include <iostream>
#include <array>

int main() {
    std::array<int, 3> arr = {1, 2, 3};
    arr[1] = 30;
    for (int i : arr) {
        std::cout << i << " ";
    }
    // 出力結果: 1 3 3
}
1 30 3

このように、添字演算子[]を使用してstd::arrayの要素を変更することができます。

要素の削除方法

std::arrayから特定の要素を削除することはできませんが、一部分だけ取り出すことは可能です。

例えば、以下のようなコードで先頭から2つ目までの要素だけ取り出すことができます。

#include <iostream>
#include <array>

int main() {
    std::array<int, 5> arr = {1, 2, 3, 4, 5};
    std::array<int, 2> sub_arr = {arr[0], arr[1]};
    for (int i : sub_arr) {
        std::cout << i << " ";
    }
    // 出力結果: 1 2
}
1 2

このように、一部分だけ取り出すことができますが、元のstd::arrayから特定の要素を削除することはできないため注意してください。

std::arrayの要素のソート方法

std::arrayは、C++のSTL(Standard Template Library)に含まれる配列クラスです。std::arrayを使用することで、配列の要素数を宣言時に指定し、安全かつ効率的な要素アクセスが可能になります。

この記事では、std::arrayの要素をソートする方法について解説します。

std::arrayの要素を昇順にソートする

std::arrayの要素を昇順にソートする場合は、以下のようにstd::sort関数を使用します。

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

int main() {
    std::array<int, 5> arr = {3, 1, 4, 2, 5};

    // 昇順にソート
    std::sort(arr.begin(), arr.end());

    for (auto&& elem : arr) {
        std::cout << elem << " ";
    }
    // 出力結果: 1 2 3 4 5

    return 0;
}
1 2 3 4 5

上記コードでは、std::sort関数を使用してarrの要素を昇順にソートしています。また、for文と範囲ベースfor文(range-based for loop)を使用して、ソート後のarrの各要素を出力しています。

std::arrayの要素を降順にソートする

std::arrayの要素を降順にソートする場合は、以下のように比較関数オブジェクト(function object)を指定したstd::sort関数を使用します。

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

int main() {
    std::array<int, 5> arr = { 3, 1, 4, 2, 5 };

    //降順ソート用の条件式式を書いたラムダ式
    auto greater_f = [](const int& a, const int& b) {
        return a > b;
    };

    // 比較関数オブジェクトで降順ソート
    std::sort(arr.begin(), arr.end(), greater_f);

    for (auto&& elem : arr) {
        std::cout << elem << " ";
    }
    // 出力結果: 5 4 3 2 1

    return 0;
}
5 4 3 2 1

上記コードでは、比較関数オブジェクトである[](const int& a, const int& b){return a > b;} を指定しています。

この比較関数オブジェクトは、「aがbより大きければtrue」つまり「aがbより優先度が高い」という条件式であり、これによって降順ソートが行われます。

std::arrayの要素の検索方法

std::arrayは、要素を格納するための固定長配列です。この配列には、様々な要素が含まれています。ここでは、std::arrayの要素を検索する方法について説明します。

まず、std::arrayの要素を検索するためには、線形探索と二分探索の2つの方法があります。

線形探索

線形探索は、配列内の各要素を順番に比較して目的の値を見つける方法です。以下は、線形探索を使用して特定の値を検索する例です。

#include <iostream>
#include <array>

int main() {
    std::array<int, 5> arr = { 1, 2, 3, 4, 5 };
    int target = 3;
    bool found = false;

    for (int i = 0; i < arr.size(); i++) {
        if (arr[i] == target) {
            found = true;
            break;
        }
    }

    if (found) {
        std::cout << "3 が見つかりました" << std::endl;
    }
    else {
        std::cout << "3 が見つかりませんでした" << std::endl;
    }

    return 0;
}
3 が見つかりました

この例では、arrという名前のstd::arrayオブジェクトが宣言されています。

その後、target変数に3が代入されます。そして、forループで配列内の各要素が順番に比較されます。もし目的の値が見つかった場合は、found変数がtrueに設定されます。

二分探索

二分探索は、ソート済み配列内で目的の値を高速に検索するアルゴリズムです。以下は、二分探索を使用して特定の値を検索する例です。

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

int main() {
    std::array<int, 5> arr = { 1, 2, 3, 4, 5 };
    int target = 3;

    if (std::binary_search(arr.begin(), arr.end(), target)) {
        std::cout << "3 が見つかりました" << std::endl;
    }
    else {
        std::cout << "3 が見つかりませんでした" << std::endl;
    }

    return 0;
}
3 が見つかりました

この例では、arrという名前のstd::arrayオブジェクトが宣言されています。その後、target変数に3が代入されます。そして、std::binary_search関数で目的の値が見つかるかどうか判断します。

std::arrayの要素の反転方法

std::arrayの要素を反転するには、std::reverse()関数を使用します。この関数は、アルゴリズムヘッダー<algorithm>に定義されています。

以下は、std::reverse()関数を使用してstd::arrayの要素を反転するサンプルコードです。

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

int main() {
    std::array<int, 5> arr = { 1, 3, 4, 5, 2 };

    // 要素を出力
    std::cout << "反転前: ";
    for (auto i : arr) {
        std::cout << i << " ";
    }
    std::cout << std::endl;

    // 要素を反転
    std::reverse(arr.begin(), arr.end());

    // 反転後の要素を出力
    std::cout << "反転後: ";
    for (auto i : arr) {
        std::cout << i << " ";
    }
    std::cout << std::endl;

    return 0;
}

上記コードでは、std::reverse()関数に対してarr.begin()arr.end()を渡すことで、配列全体の要素が反転されます。最初に配列内の要素を出力し、その後に反転後の要素も出力しています。

実行結果は以下のようになります。

反転前: 1 3 4 5 2
反転後: 2 5 4 3 1

以上が、std::arrayの要素を反転する方法です。

std::arrayの要素のコピー方法

std::arrayの要素をコピーするには、以下の2つの方法があります。

1. std::array::operator=()関数を使用する方法

#include <iostream>
#include <array>

int main()
{
    std::array<int, 5> arr1 = {1, 2, 3, 4, 5};
    std::array<int, 5> arr2;

    // arr1からarr2へ要素をコピーする
    arr2 = arr1;

    // コピーされたarr2の要素を表示する
    for (auto i : arr2) {
        std::cout << i << " ";
    }

    return 0;
}
1 2 3 4 5

上記の例では、arr1からarr2へ要素をコピーしています。=演算子によって、arr1からarr2へ全ての要素がコピーされます。

2. std::copy()関数を使用する方法

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

int main()
{
    std::array<int, 5> arr1 = {1, 2, 3, 4, 5};
    std::array<int, 5> arr2;

    // arr1からarr2へ要素をコピーする
    std::copy(arr1.begin(), arr1.end(), arr2.begin());

    // コピーされたarr2の要素を表示する
    for (auto i : arr2) {
        std::cout << i << " ";
    }

    return 0;
}
1 2 3 4 5

上記の例では、std::copy()関数によって、arr1からarr2へ全ての要素がコピーされます。

この場合は、イテレーター(begin()end())と出力先(arr2.begin())が必要であり、arr2 = arr1よりも冗長になりますが、2番目から4番目だけを複製するといったコピーが可能です。

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

int main()
{
    std::array<int, 5> arr1 = { 1, 2, 3, 4, 5 };
    std::array<int, 5> arr2 = { 5, 6, 7, 8, 9 };

    // arr1の0番目から2番目までをarr2へ要素をコピーする
    auto it = arr1.begin();
	std::copy(it, it + 3, arr2.begin());

    // コピーされたarr2の要素を表示する
    for (auto i : arr2) {
        std::cout << i << " ";
    }

    return 0;
}
1 2 3 8 9

以上がstd::arrayで配列間で値をコピーする方法です。

std::arrayの要素の比較方法

std::arrayでは、要素同士を比較するために、以下の演算子が用意されています。

  • == : 2つのstd::arrayが等しい場合にtrueを返す
  • != : 2つのstd::arrayが異なる場合にtrueを返す
  • < : 左辺が右辺より小さい場合にtrueを返す
  • <= : 左辺が右辺以下である場合にtrueを返す
  • > : 左辺が右辺より大きい場合にtrueを返す
  • >= : 左辺が右辺以上である場合にtrueを返す

これらの演算子は、bool型で結果が返されます。また、要素同士の比較は、先頭から順番に行われます。つまり、最初の要素から順番に比較していき、異なる値が見つかった時点でその大小関係が決定されます。

以下は、std::array同士を比較するサンプルコードです。

#include <iostream>
#include <array>

int main() {
    std::array<int, 3> a1 = { 1, 2, 3 };
    std::array<int, 3> a2 = { 1, 2, 3 };
    std::array<int, 3> a3 = { 4, 5, 6 };

    if (a1 == a2) {
        std::cout << "a1 と a2 は同じ要素を持つ配列です" << std::endl;
    }
    else {
        std::cout << "a1 と a2 異なる要素を持つ配列です" << std::endl;
    }

    if (a1 == a3) {
        std::cout << "a1 と a3 同じ要素を持つ配列です" << std::endl;
    }
    else {
        std::cout << "a1 と a3 異なる要素を持つ配列です" << std::endl;
    }

    return 0;
}
a1 と a2 は同じ要素を持つ配列です
a1 と a3 異なる要素を持つ配列です

このコードでは、まず3つのstd:;array変数a1, a2, a3 を宣言しています。

そして、if (a1 == a2) の部分で==演算子を使ってa1a2 を比較しています。

この結果、a1 と a2 は同じ要素を持つ配列ですというメッセージが表示されます。

次に、同じような方法でif (a1 == a3) の部分でも比較しています。

しかし今度は異なる値が含まれているため、a1 と a3 異なる要素を持つ配列ですというメッセージが表示されます。

std::arrayの多次元配列の宣言方法

std::arrayは、1次元の配列を扱うことができますが、多次元の配列も宣言することができます。

例えば、2次元のint型配列を宣言する場合は以下のようになります。

#include <array>

std::array<std::array<int, 3>, 2> arr = {{
    {1, 2, 3},
    {4, 5, 6}
}};

この場合、std::array<int, 3>が要素となる1次元配列を要素として持つstd::array<std::array<int, 3>, 2>を宣言しています。

初期化時には、外側の波括弧で囲まれた部分が各行に対応し、内側の波括弧で囲まれた部分が各行の要素に対応します。上記の例では、{1, 2, 3}が最初の行に対応し、{4, 5, 6}が次の行に対応します。

実際に要素にアクセスする際は、通常の二次元配列と同じようにarr[1][2]のようにアクセスできます。

#include <iostream>
#include <array>

int main() {
    std::array<std::array<int, 3>, 2> arr = { {
      {1, 2, 3},
      {4, 5, 6}
  } };

    std::cout << "arr[0][0] = " << arr[0][0] << std::endl;
    std::cout << "arr[0][1] = " << arr[0][1] << std::endl;
    std::cout << "arr[1][2] = " << arr[1][2] << std::endl;

    return 0;
}
arr[0][0] = 1
arr[0][1] = 2
arr[1][2] = 6

std::arrayの注意点

td::arrayは通常の配列の正統強化版ともいえるコンテナクラスですが、使用する上でいくつかの注意点があります。

固定長であること

std::arrayは、宣言時に要素数を指定する必要があります。

そのため、実行時に要素数を変更することはできません。もし可変長の配列が必要な場合は、代わりにstd::vectorを使用しましょう。

メモリ効率

std::arrayは静的な配列であるため、メモリ効率がよくなります。しかし、動的なサイズ変更が必要な場合には向いていません。

配列外アクセス

std::arrayでは範囲外アクセスチェックが行われず、配列外へのアクセスも可能です。そのため、プログラム中で範囲外アクセスしないよう注意する、必要に応じて例外処理を用意する必要があります。

以上がstd::arrayを使用する際に注意すべき点です。これらの点に留意してプログラムを作成すれば、安全かつ効率的なコードを書くことができます。

目次