C++で配列の要素数を動的に確保したい場合に使う「std::vector」
std::vector 基本的な使い方
int型の可変長配列を定義して、色々操作してみます。
#include <vector>
#include <iostream>
int main()
{
// int型の可変長配列を定義しつつ初期化
std::vector<int> v = { 1, 3, 5, 7, 10 };
v.push_back(100); // 末尾に要素を追加する {1,3,5,7,10,100}
std::size_t size = v.size(); // 要素数を取得する 6
v.insert(v.begin() + 1, 8); // 1番目に値を追加する {1,8,3,5,7,10,100}
v.erase(v.begin() + 3); // 3番目の要素を削除する {1,8,3,7,10,100}
// 先頭から全ての要素に対して処理を行う
for (auto i : v) {
std::cout << i << std::endl;
}
v.clear(); // 要素の全削除 {}
}
std::vector 概要
vectorの各要素は線形に順序を保ったまま格納されます。
各要素がメモリ上で連続した領域に配置されるため、各要素へのランダムアクセスが高速に行えます。
領域の確保、拡張は自動的に行われます。(拡張に備え実際の要素数より少し余分にメモリが確保される)
領域の再確保が発生する場合は、全ての要素が新しい領域にコピーされます。(連続した領域に配置されるため)
その際は非常にコストがかかるので、要素数が大きくなると分かっている場合は「reserve()」メンバ関数で予め領域を確保した方が良い。
std::vectorの構築
まずは、std::vectorの構築です。
リストから構築する
初期値を{~, ~, ~, ~}で指定して、std::vectorを構築します。
#include <vector>
int main()
{
std::vector<int> num_vector = { 1, 2, 4, 6, 8 };
std::vector<std::string> str_vector = { "aaa", "bbb", "ddd" };
}
空の配列を構築する
要素数0の空のstd::vectorを構築します。
#include <vector>
int main()
{
std::vector<int> num_vector; // 空の配列
std::vector<std::string> str_vector; // 空の配列
}
std::vectorに要素を追加する
構築後のstd::vectorに要素を追加する方法です。
push_back()で一番後ろに要素を追加する
push_backを使って、配列の末尾に新たな要素を追加します。
#include <vector>
#include <iostream>
int main()
{
std::vector<int> number; // 空の配列を構築
number.push_back(1);
number.push_back(2);
number.push_back(5);
for (auto num : number) {
std::cout << num << std::endl;
}
}
【出力】
1
2
5
insert()で任意の位置に要素を追加する
insertを使って、配列の任意の位置に新たな要素を追加します。
#include <vector>
#include <iostream>
int main()
{
std::vector<int> number = { 1, 2, 5, 7 }; // 要素数4の配列を構築
// 2番目に「8」を追加する
int n = 8;
number.insert(number.begin()+1, n);
// 3番目に「10」を追加する
number.insert(number.begin()+2, 10);
// 末尾に「20」を追加する
number.insert(number.end(), 20);
for (auto num : number) {
std::cout << num << std::endl;
}
}
【出力】
1
8
10
2
5
7
20
要素へアクセスする
配列の各要素へのアクセスです。
atを使って要素にアクセスする
at(n)でn番目の要素を参照します。要素番号(n)を指定する際、先頭の要素は0番目となります。
nが配列の要素数以上の場合は、「out_of_range」例外が送出されます。
#include <vector>
#include <iostream>
int main()
{
std::vector<int> number = { 1, 2, 5, 7 }; // 要素数4の配列を構築
// 3番目の要素を参照する
auto num = number.at(3);
std::cout << num << std::endl;
// 範囲外のアクセス
num = number.at(4); // out_of_range送出
}
【出力】
7
operator[]を使って要素にアクセスする
[n]でn番目の要素を参照します。要素番号(n)を指定する際、先頭の要素は0番目となります。
nが配列の要素数以上の場合は、未定義の動作となります。境界チェックが行われる場合もあれば、予期せぬ値を参照する場合もあります。
#include <vector>
#include <iostream>
int main()
{
std::vector<int> number = { 1, 2, 5, 7 }; // 要素数4の配列を構築
// 2番目の要素を参照する
auto num = number[2];
std::cout << num << std::endl;
}
【出力】
5
std::vectorから要素を削除する
std::vectorから要素を削除する方法です。
eraseを使って要素を削除する
eraseを使って特定の位置の要素、もしくは特定の範囲の要素を削除します。
#include <vector>
#include <iostream>
int main()
{
// 単一の削除
{
std::vector<int> number = {1, 2, 3, 4, 5, 6};
number.erase(number.begin() + 3);
std::cout << "[1] ";
for (auto num : number) {
std::cout << num;
std::cout << " ";
}
std::cout << std::endl;
}
// 複数の削除
{
std::vector<int> number = {1, 2, 3, 4, 5, 6};
number.erase(number.begin(), number.begin() + 3);
std::cout << "[2] ";
for (auto num : number) {
std::cout << num;
std::cout << " ";
}
std::cout << std::endl;
}
}
【出力】
[1] 1 2 3 5 6
[2] 4 5 6
eraseとfor文を使って複数の項目を削除する
for文で各要素の内容をチェックしつつ、eraseで特定の要素を削除します。
#include <vector>
#include <string>
#include <iostream>
int main()
{
std::vector<std::string> str = { "cat", "dog", "rabbit", "mouse", "fox", "horse" };
// vector内の文字列で「t」が含まれている文字列を削除する
for (auto it = str.begin(); it != str.end();) {
if (it->find('t') != std::string::npos) {
it = str.erase(it); // 削除された要素の次をさすイテレータが戻る
} else {
++it; // 要素を削除しない場合は、イテレータを進める
}
}
for (auto s : str) {
std::cout << s << std::endl;
}
}
【出力】
dog
mouse
fox
horse
pop_backを使って最後の要素を削除する
pop_backを使って、最後の要素を削除します。
#include <vector>
#include <iostream>
int main()
{
std::vector<int> number = { 1, 2, 3, 4, 5 };
number.pop_back(); // 最後の要素を削除する
for (auto num : number) {
std::cout << num << std::endl;
}
}
【出力】
1
2
3
4
clearを使って全要素を削除する
clearを使って、vector内の全ての要素を削除します。
#include <vector>
#include <iostream>
int main()
{
std::vector<int> number = {1, 2, 3, 4, 5, 6, 7, 8 };
std::cout << "before size : " << number.size() << std::endl;
number.clear(); // 全要素を削除する
std::cout << "after size : " << number.size() << std::endl;
}
【出力】
before size : 8
after size : 0