C++の基礎 - STL(array)

提供:MochiuWiki - SUSE, Electronic Circuit, PCB
2021年9月1日 (水) 02:47時点におけるWiki (トーク | 投稿記録)による版 (ページの作成:「== 概要 == <code>std::array</code>は、C++11で追加された固定長配列のコンテナクラスである。<br> <code>std::vector</code>に存在する<code>size…」)
(差分) ← 古い版 | 最新版 (差分) | 新しい版 → (差分)
ナビゲーションに移動 検索に移動

概要

std::arrayは、C++11で追加された固定長配列のコンテナクラスである。
std::vectorに存在するsizeメソッドやbackメソッド等の便利な機能が使用できる。


データ構造

std::arrayは、std::vectorstd::listのようなデータ構造を持たず、通常配列と同じように要素のためにだけメモリを消費する。
std::vectorと比較してメモリ効率が良いが、要素数が多い場合はその効果は期待できない。

std::arrayの交換においては、中身のデータを交換するしかなく、O(N)の処理時間を要する。
std::vector等は、データ領域へのポインタを交換するだけであるため、O(1)の処理時間で済む。


宣言と初期化

宣言

std::arrayは、以下のように宣言する。
要素数は、0以上の整数を指定する。

 #include <array>
 
 std::array<データ型, 要素数> <オブジェクト名>;


以下の例では、int型の要素数10のオブジェクトを宣言している。
宣言のみを行う場合、要素はデフォルト値(整数であれば0)に初期化される。

 #include <array>
 
 std::array<int, 10> ar;     // int型、要素数10


初期化リストによる初期化

初期化リストを使って、各要素を初期化することができる。

 std::array<int, 4> ar{1, 2, 3, 4};     // int型、要素 = {1, 2, 3, 4}


初期化リストの要素数が配列要素数より少ない場合、デフォルト値で初期化される。

 std::array<int, 4> ar{1, 2};     // ar[2], ar[3] は 0 で初期化される。


初期化リストの要素数が配列要素数より多いと、コンパイルエラーとなる。

 std::array<int, 2> ar{1, 2, 3, 4};     // コンパイルエラーとなる


通常の配列であれば、int ar[] = {1, 2, 3, 4};のように要素数を省略できるが、std::arrayでは、要素数を省略できないことに注意すること。

コピーコンストラクタ

コピーコンストラクタとは、同じ型のオブジェクトを渡され、それと同様の内容のオブジェクトを生成するコンストラクタのことである。
std::arrayでは、コピー元オブジェクトと生成するオブジェクトは同じデータ型かつ同一サイズであることに注意すること。

std::array<データ型, サイズ> オブジェクト名(コピー元のオブジェクト名);


以下の例では、オブジェクトXをコピーして、{1, 2, 3}という値をもつオブジェクトYを生成している。

 std::array<int, 3> X{1, 2, 3};
 std::array<int, 3> Y(X);        // コピーコンストラクタ



値の参照と代入

[]演算子(operator[](int))を使用して、通常の配列と同様に、配列要素値の参照・代入が可能である。
ここで、operator[](int)とは、通常の配列の要素にアクセスする時と同様の記述である。(例. ar[10])

以下の例では、配列要素値の参照と代入をしている。(通常の配列要素の参照・代入と同様)

 constexpr int SZ = 10;  // 要素数
 std::array<int, SZ> ar{3, 1, 4, 1, 5, 9, 2, 6, 5, 3};
 
 for (int i = 0; i < SZ; i++)
 {
    std::cout << ar[i];  // arのi番目の要素を表示
 }


 constexpr int SZ = 10;  // 要素数
 std::array<int, SZ> v;  // 指定要素数でstd::arrayを生成
 
 for (int i = 0; i < SZ; i++)
 {
    v[i] = i;            // 要素を 0, 1, 2, 3, ... 9 に設定
 }



メンバ関数

std::arrayの状態を取得

  • bool empty()
  • size_t size()


emptyメソッドは、配列が空かどうかを判定する。
空ならばtrue、空でなければfalseを返す。

これは、後述するsize() == 0と判定するのと同等であるが、コンテナクラスによっては、sizeメソッドよりもemptyメソッドの方が高速な場合があるため、
std::array等のコンテナクラスに対しては、emptyメソッドを使用することが推奨されている。

 if(!ar.empty())
 {  // arが空ではない場合
    // ...処理
 }


sizeメソッドは、要素数を返す関数である。(size_t型は、符号なし整数の組み込み型である)

 for(int i = 0; i != ar.size(); i++)
 {  // 全要素に対するループ
    // ...処理
 }


std::arrayの要素を取得

  • front() : 要素の型への参照
  • back() : 要素の型への参照
  • data() : 要素の型へのポインタ


frontメソッドは、先頭要素への参照を返す。(オブジェクト名[0]と同等)

backメソッドは、末尾要素への参照を返す。(オブジェクト名[オブジェクト名.size() - 1]と同等)

 if(!ar.empty())
 {
    auto f = ar.front();  // 最初の要素
    auto b = ar.back();   // 最後の要素
    // ...略
 }


また、frontメソッドおよびbackメソッドは、先頭または末尾の要素への参照を返すため、先頭または末尾の要素へ代入することもできる。

 std::array<int, 4> ar{1, 2, 3, 4};
 
 ar.front() = 11;  // 最初の要素を 11 に変更
 ar.back() = 44;   // 最後の要素を 44 に変更


dataメソッドは、std::arrayの先頭アドレスを返す。(&オブジェクト名[0]と同等)
std::arrayは、通常配列と同様にデータ領域が連続したアドレスだということが保証されているため、データアドレスを他の関数に渡して処理することもできる。

 std::array<int, 4> ar{1, 2, 3, 4};
 
 int *ptr = ar.data();  // ptrはarの先頭要素へのポインタ
 cout << *ptr << "\n";  // ptrが指す値(1)が表示される