vector
■STL
STLとはStandard Template Libraryの略で、
C++が提供しているテンプレートクラスを使用したライブラリです。
STLには配列などの複数のデータを管理するためのクラスが多数用意されています。
コンテナオブジェクト:
複数のデータを格納し、管理するオブジェクトを
コンテナ、またはコンテナオブジェクトと呼ばれています。
vectorやlistはコンテナオブジェクトにあたります。
■vector
vectorは動的配列のテンプレートクラスです。
特徴は通常の配列はサイズを最初に決める必要がありますが、
vectorは要素数が足りない場合、自動的に要素を追加してくれます。
●宣言:
必須ヘッダ:
vector
要素指定無し:
書式例:
std::vector<データ型> 変数名;
具体例:
std::vector<int> iv;
要素指定有り:
書式例:
std::vector<データ型> 変数名(要素数)
具体例:
std::vector<int> iv(100); // 要素数100
要素指定有り(要素の初期化):
書式例:
std::vector<データ型> 変数名(要素数, 初期値)
具体例:
std::vector<int> iv(100, 5); // 要素数100、初期値5
要素指定有り(配列指定):
書式例:
std::vector<データ型> 変数名(配列の先頭ポインタ、配列の末尾のポインタ)
具体例:
int array[] = { 1, 2, 3 };
std::vector<int> iv(array, std::end(array));
std::end:
配列の末尾のポインタを返してくれる
●配列の参照と代入
配列の参照と代入は通常の配列と同様に「[]」で行えます。
例:
std::vector<int> vi(10, 0);
// 代入
for (int i = 0; i < 10; i++)
{
vi[i] = i;
}
// 参照
for (int i = 0; i < 10; i++)
{
std::cout << vi[i] << std::endl;
}
●サイズ関連
配列の要素数取得:
配列のサイズはsize関数を使用することで取得することが可能です。
関数名:
size
戻り値:
配列の要素数
引数:
なし
内容:
vectorで作成している配列の要素数を返す
例:
std::vector<int> vi(10);
std::cout << vi.size() << std::endl;
出力結果:
10
配列の有無
動的配列を確保しているかどうかの判定はemptyで行うことができます。
関数名:
empty
戻り値:
true:
動的配列が存在しない(空)
false:
動的配列が存在する
内容:
vector変数が動的に配列を確保しているかどうかを判断して
その結果を返す
具体例:
std::vector<int> vi;
std::vector<int> vi2(10);
if (vi.empty() == false)
{
cout << "viは動的確保している" << std::endl;
} else {
cout << "viは動的確保していない" << std::endl;
}
if (vi2.empty() == false)
{
cout << "vi2は動的確保している" << std::endl;
} else {
cout << "vi2は動的確保していない" << std::endl;
}
●データ追加
末尾追加:
データの追加はpush_backを使用します。
関数名:
push_back
戻り値:
なし
引数:
追加データ
内容:
データを末尾に追加する
具体例:
std::vector<int> vi(10, 0);
std::cout << vi.size() << std::endl;
// 配列の末尾に5を追加
vi.push_back(5);
std::cout << vi.size() << std::endl;
出力結果:
10
11
末尾追加(クラス):
emplace_backは末尾にクラスのインスタンスを追加します。
emplace_backを使用することでインスタンスを作成してから
配列に追加しなくてもよくなります。
関数名:
emplace_back
戻り値:
なし
引数:
vectorで指定したクラスのコンストラクタ引数
内容:
末尾にクラスのインスタンスを追加する
引数にコンストラクタの引数を渡すことで、
関数内でクラスのインスタンスを作成して追加してくれる
emplace_back未使用例:
class Test
{
public:
Test(int a)
{
std::count << "コンストラクタ" << a << std::endl;
}
};
void main(void)
{
std::vector<Test> vt;
Test t1(1);
Test t2(2);
vt.push_back(t1);
vt.push_back(t2);
}
出力結果:
コンストラクタ1
コンストラクタ2
emplace_back使用例:
class Test
{
public:
Test(int a)
{
std::count << "コンストラクタ" << a << std::endl;
}
};
void main(void)
{
std::vector<Test> vt;
vt.emplace_back(10);
vt.emplace_back(11);
}
出力結果:
コンストラクタ10
コンストラクタ11
挿入:
挿入はiteratorの解説後に再度説明します。
●削除
末尾削除:
pop_back関数は最後の要素を削除する関数です。
関数名:
pop_back
戻り値:
なし
引数:
なし
内容:
動的配列の要素の末尾のデータを削除する
具体例:
std::vector<int> vi(10);
std::cout << vi.size() << std::endl;
vi.pop_back();
std::cout << vi.size() << std::endl;
出力結果:
10
9
位置指定削除:
位置指定削除はiteratorの解説後に再度説明します。
■iterator
iteratorは抽象化されたポインタのことです。
簡単にいうと「どのデータ型にも対応可能なポインタ」です。
vectorやlistなどのコンテナオブジェクトは様々なデータ型を格納しています。
それらのデータ型にとらわれずデータを扱う方法がこのイテレータを使用した方法です。
●書式:
書式例:
std::vector<データ型>::iterator 変数名;
具体例:
std::vector<int> vi(10, 0);
std::vector<int>::iterator first, end, itr;
●概要
イテレータはコンテナオブジェクトで型として用意されています。
コンテナオブジェクトには配列の最初を取得するbeginと最後を取得するendが
用意されており、それらのデータを使用して配列の要素を全て調べることができます。
イテレータのbeginからendまでは連続したアドレスになっているので、
beginの位置は[0]、beginの位置 + 1は[1]と考えることができます。
また、イテレータに内包されているデータにアクセスする場合は
変数の前に「*」をつけることで参照等が可能です。
具体例:
std::vector<int> vi(10, 0);
std::vector<int>::iterator first, end, itr;
first = vi.begin();
end = vi.end();
for (itr = first; itr != end; itr++)
{
*itr = 10;
}
for (itr = first; itr != end; itr++)
{
std::cout << *itr << std::endl;
}
●auto
イテレータの使用方法として「auto」という
データ型を使用することもあります。
autoを使うことでイテレータの長い変数名を大幅に短縮することが可能であり、
変数自体は通常のイテレータと同様に扱うことができます。
例:
std::vector<int> vi(10, 0);
for (auto itr = vi.begin(); itr != vi.end(); itr++)
{
*itr = 10;
}
for (auto itr = vi.begin(); itr != vi.end(); itr++)
{
std::cout << *itr << std::endl;
}
■任意位置挿入、任意位置削除
●任意位置挿入
任意の位置にデータを挿入するにはinsert関数を使用します。
挿入位置の指定はiteratorを使用します。
関数名:
insert
戻り値:
iterator:
挿入したデータのiterator
引数:
第一引数:
iterator:
挿入位置
第二引数:
挿入データ
内容:
引数で指定した位置にデータを挿入する
例:
std::vector<int> vi(10, 0);
// 配列[1]に100を追加
std::vector<int>::iterator i = vi.insert(vi.begin() + 1, 100);
std::cout << *i << std::endl;
出力結果:
100
●任意位置削除
配列の任意のデータを削除するにはerase関数を使用します。
削除位置の指定にはiteratorを使用します。
関数名:
erase
戻り値:
削除した次の位置のiterator
引数:
その①.
iterator:
削除位置
その②.
iterator first:
削除位置の開始
iterator end:
削除位置の終端
内容:
配列のデータを削除する
引数その①では指定した位置のデータを削除し、
引数その②ではfirstの位置からendの位置 - 1までのデータを一気に削除する
std::vector<int> vi(10, 0);
// 配列の[0]を削除
vi.erase(vi.begin());
// 配列の[2]~[4]までを削除
vi.erase(vi.begin() + 2, vi.begin() + 5);
for (auto itr = vi.begin(); itr != vi.end(); itr++)
{
std::cout << *itr << std::endl;
}
出力結果
0
0
0
0
0
0