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