C++の基礎 - STL(array)
概要
std::array
は、C++11で追加された固定長配列のコンテナクラスである。
std::vector
に存在するsize
メソッドやback
メソッド等の便利な機能が使用できる。
データ構造
std::array
は、std::vector
やstd::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)が表示される