C++の基礎 - STL(vector)
概要
C++ STLでは、vectorクラス(以下、vectorと呼ぶ)が存在する。
ここでは、vectorの基本的な使い方や利点について記載する。
vectorの利点
- size()で配列要素数を参照できるため、関数に渡しやすい。(アドレス渡し、参照渡しが可能)
- size()でインデックスの上限を指定すると境界エラーが起きない。
- resize(要素数)で要素数を変更できる。
- push_back(データ)で1つずつ要素を追加できる。
- =(代入演算子)でvecorクラスがコピーできる。
- 関数の戻り値に指定できる。
- STLのalgorithmでソートできる。
- erase(インデックス)で指定要素のみ削除できる。
- 1行でstring型にargvを格納できる。
vectorを使用する前に
vectorを使用するためには、以下ののヘッダファイルをインクルードする必要がある。
#include <vector>
宣言と初期化
1次元配列
1次元配列のvectorの宣言は以下の通りである。
intやdouble等の基本的な型のみならず、任意で作成したクラスも使用できる。
ここで、Tはデータ型、Nは要素数、dは初期化する値を表すものとする。
vector<T> v;
vector<T> v();
vector<T> v(N);
vector<T> v(N, d);
2次元配列
2次元配列のvectorの宣言は以下の通りである。
ここで、Mは要素数を表すものとする。
vector<vector<T>> vv;
vector<vector<T>> vv();
vector<vector<T>> vv(N);
vector<vector<T>> vv(N, vector<T>(M));
vector<vector<T>> vv(N, vector<T>(M, d));
要素へのアクセス
vectorでは、通常の配列と同様の記述で要素へアクセスすることができる。
1次元配列
v[]のi番目にdを代入して、それを出力する場合は以下となる。
v[i] = d;
cout << v[i] << endl;
2次元配列
v[][]のi番目およびj番目にdを代入して、それを出力する場合は以下となる。
v[i][j] = d;
cout << v[i][j] << endl;
要素数の変更
vectorでは、配列の要素数を変更することができる。
1次元配列
v[]の要素数をN個に変更する場合は以下の通りである。
v.resize(N);
2次元配列
vv[][]の要素数をN * Nに変更する場合は以下の通りである。
// 方法 1
vv.resize(N);
for(int i = 0; i < N; i++)
{
vv[i].resize(N);
}
// 方法 2
vv.resize(N, vector<T>(N));
末尾に要素を追加
1次元配列
v[]の末尾にデータを追加する場合は以下の通りである。
v.push_back(d);
2次元配列
vv[][]のi番目の末尾にデータを追加する場合は以下の通りである。
vv[i].push_back(d);
vectorのコピー
vectorをコピーする方法は複数存在する。
ここでは、v1[]をv2[]にコピーする方法を記述する。
// 方法 1
v2 = v1
// 方法 2
v2.resize(v1.size());
for(int i = 0; i < v1.size(); i++)
{
v2[i] = v1[i];
}
// 方法 3
copy(v1.begin(), v1.end(), v2.begin());
vectorの全要素を末尾に追加
v1[]をv2[]の末尾に追加する方法は以下の通りである。(方法3が最も簡潔)
// 方法 1
int size = v2.size();
v2.resize(size + v1.size());
for(int i = 0; i < v1.size(); i++)
{
v2[i + size] = v1[i];
}
// 方法 2
for(int i = 0; i < v1.size(); i++)
{
v2.push_back(v1[i]);
}
// 方法 3
copy(v1.begin(), v1.end(), back_inserter(v2));
指定範囲をコピー
v1[]のa番目からb番目をv2[]にコピーする方法は以下の通りである。(方法2が簡潔)
// 方法 1
v2.resize(b - a);
for(int i = 0; i < v2.size(); i++)
{
v2[i] = v1[a + i];
}
// 方法 2
copy(v1.begin() + a, v1.begin() + b, v2.begin());
vectorを関数の引数にする
vectorは簡単に関数の引数にすることができる。
また、vectorのメンバ関数から要素数を参照することができるため、関数内で簡単にループ数を指定できる。
ここでは、総和を求めるプログラムとvectorの全要素を表示するプログラムを例として挙げる。
ただし、処理時間などの理由から参照渡しを使用して、vectorの内容を変更しない場合はconstを付加する。
配列の総和を求めるプログラム
T SumVector(const vector<T> &v)
{
T sum = 0;
for(int i = 0; i < v.size(); i++)
{
sum += v[i];
}
return sum;
}
=== vectorの全要素を表示するプログラム
// 1次元vector
void view(const vector<T> &v)
{
for(int i = 0; i < v.size(); i++)
{
cout << v[i] << " ";
}
cout << endl;
}
// 2次元vector
void view(const vector<vector<T>> &vv)
{
for(int i = 0; i < vv.size(); i++)
{
for(int j = 0; j < vv[i].size(); j++)
{
cout << vv[i][j] << " ";
}
cout << endl;
}
}