C++には、通常の配列と同じようなデータ構造でありながら、サイズを自由に変更できる vector というデータ型があります。
今回は、C++で vectorを使用する方法について解説したいと思います。
基本構文から各メンバ関数の使い方についてなど、詳しく説明していきたいと思いますので、ぜひ参考にしてみてください。
C++のvectorとは?
vectorは、シーケンスコンテナーと呼ばれるデータ構造の一種で、C++ の配列を拡張したクラスのことを言います。
C++の配列は、いわゆる固定長配列と呼ばれるデータ構造であり、宣言時に指定したサイズを後から変更することができない仕様となっています。
一方、vectorは可変長配列と呼ばれるデータ構造で、配列のサイズを自由に変更することができるため、扱うデータの数が動的に変換するケースなどで活用することができます。
vectorの使い方
それでは早速、vectorの使い方を確認していきましょう。
宣言時の基本構文
vectorを使用する際は、以下のコードを記述してライブラリをインクルードしておきましょう。
#include <vector>宣言時の基本構文は次のとおりです。
std::vector<データ型> 変数名;宣言と同時に要素数や初期値を設定する場合は、以下のように記述します。
std::vector<データ型> 変数名(要素数);
std::vector<データ型> 変数名(要素数, 初期値); // 同じ値で全ての要素を初期化C++11以降であれば、以下の形式で配列の要素を直接指定することも可能です。
std::vector<データ型> 変数名 = {要素1,要素2};宣言した配列の各要素にアクセスする際は、該当の要素に紐づくインデックスを指定します。
#include <iostream>
#include <vector>
int main() {
std::vector<int> sample = {1, 2, 3};
std::cout << sample[0] << std::endl;
std::cout << sample[1] << std::endl;
std::cout << sample[2] << std::endl;
return 0;
}【実行結果】
1
2
3インデックスは、配列の先頭から順に 0, 1, 2 … と数えていきます。
ループを利用してvectorの各要素へアクセスする
配列内の要素を順に取得したい場合は、for文を使用するのが効率的です。
for文を使ったアクセス方法には、いくつかの種類があります。
それぞれ確認してみましょう。
for文とインデックスでvectorの要素を取得する
1つ目の取得方法は、for文のループカウント数をインデックスとして利用し、要素を取得する方法です。
各ループごとに自動で増減するカウント数を使用することで、配列内の各要素に順にアクセスすることができます。
int main() {
std::vector<int> sample = {1, 2, 3};
for (int i = 0; i < sample.size(); i++)
std::cout << sample[i] << std::endl;
return 0;
}【実行結果】
1
2
3カウント数を使用してアクセスする場合は、size() で配列の要素数を取得し、ループ回数が指定サイズを超えないよう調整しましょう。
(size については後ほど紹介します)
範囲for文でvectorの全要素を取得する
C++11以降では、範囲for文と呼ばれるループ構文を使用することもできます。
通常のfor文は、先ほどのように、ループ度に増減する数値を変数で管理します。
一方、範囲for文の場合は、数値ではなく配列の要素を順に変数へと格納するのが特徴です。
これにより、配列内の各要素を扱う際に、for文よりも簡潔にコードを記述できるメリットがあります。
以下のサンプルコードを見てみましょう。
int main() {
std::vector<int> sample = {1, 2, 3};
for (const auto& num: sample)
std::cout << num << std::endl;
return 0;
}処理内容は、先ほどのインデックスで取得する場合の例と同じですが、こちらの方がコード量はわずかに少なくなっています。
また、for文の変数に要素が直接代入されるため、変数や処理がどの内容を扱っているのかが視覚的に分かりやすくなる効果もあります。
変数名の前に記述されている autoは、型推論と呼ばれるキーワードです。
特定の型を指定する代わりにこのキーワード使うことにより、代入する値の型を自動で判別してくれるため、よりコードを簡潔にまとめることができます。
イテレーターの使い方
vectorでは、イテレーターを使用して要素にアクセスすることもできます。
イテレーターとは、配列やコンテナなどの要素に対する反復処理を抽象化したもののことを言います。
C++におけるイテレータは、組み込み配列に対するポインタ(メモリのアドレスを保持する変数)が基本となっており、使用することで要素間の移動や参照・変更などを行うことができます。
イテレーターの型は以下のように指定できますが、記述が長くなるため autoを使用する場合が多いです。
std::vector<データ型>::iterator 変数名;要素の参照や変更を行う場合は、*を付けることでアクセスできます。
また、インクリメント(++) やデクリメント(—) を付けることで、対象とする要素の前後に移動することができます。
int main() {
std::vector<int> sample = {1, 2, 3};
std::vector<int>::iterator itrBegin = sample.begin(); // 先頭要素を示すイテレータを取得
auto itrEnd = sample.end(); // 末尾要素の次を示すイテレータを取得
// 要素を参照
std::cout << *itrBegin << std::endl;
// 要素を変更
*itrBegin = 5;
std::cout << sample[0] << std::endl;
// 参照先を移動
++itrBegin;
--itrEnd;
std::cout << *itrBegin << std::endl;
std::cout << *itrEnd << std::endl;
return 0;
}【実行結果】
1
5
2
3vectorのメンバ関数の使い方
vectorには、配列を操作するための様々なメンバ関数が用意されています。
代表的ないくつかのメンバ関数について、順に見ていきましょう。
push_back / emplace_back で末尾に要素を追加する
配列の末尾に要素をしたい場合に活用できるのが、push_back() / emplace_back() です。
emplace_backは、C++11以降で使用することができるメンバ関数で、内部動作の違いにより push_backよりも高速に動作する場合があります。
int main() {
std::vector<int> sample = {1, 2, 3};
std::cout << "追加前:" << std::endl;
for(const auto& num: sample)
std::cout << num << std::endl;
// 要素を追加
sample.push_back(4);
sample.emplace_back(5);
std::cout << "追加後:" << std::endl;
for(const auto& num: sample)
std::cout << num << std::endl;
return 0;
}【実行結果】
追加前:
1
2
3
追加後:
1
2
3
4
5insert / emplace で要素を挿入・連結する
末尾ではなく、配列の途中に要素を挿入したい場合は、insert() / emplace() を使用します。
こちらも、関数によって得られる結果は同じものですが、内部動作の違いにより emplaceの方が効率よく動作する場合があります。
int main() {
std::vector<int> sample = {1, 2, 3};
std::cout << "追加前:" << std::endl;
for(const auto& num: sample)
std::cout << num << std::endl;
// 要素を追加
sample.insert(sample.begin() + 1, 4);
sample.emplace(sample.begin() + 2, 5);
std::cout << "追加後:" << std::endl;
for(const auto& num: sample)
std::cout << num << std::endl;
return 0;
}【実行結果】
追加前:
1
2
3
追加後:
1
4
5
2
3pop_back で末尾の要素を削除する
pop_back() を使用すると、末尾の要素を削除することができます。
int main() {
std::vector<int> sample = {1, 2, 3};
std::cout << "削除前:" << std::endl;
for(const auto& num: sample)
std::cout << num << std::endl;
// 要素を削除
sample.pop_back();
std::cout << "削除後:" << std::endl;
for(const auto& num: sample)
std::cout << num << std::endl;
return 0;
}【実行結果】
削除前:
1
2
3
削除後:
1
2erase で要素を削除する
任意の箇所の要素を削除したい場合は、erase()を使用します。
int main() {
std::vector<int> sample = {1, 2, 3};
std::cout << "削除前:" << std::endl;
for(const auto& num: sample)
std::cout << num << std::endl;
// 要素を削除
sample.erase(sample.begin() + 1);
std::cout << "削除後:" << std::endl;
for(const auto& num: sample)
std::cout << num << std::endl;
return 0;
}【実行結果】
削除前:
1
2
3
削除後:
1
3size で要素数を取得する
配列に含まれる要素の数を取得したい場合は、size() を使用します。
for文のループ回数の指定時や、要素の位置指定時など、対象の配列のサイズを基準に処理を行いたい場合に有効です。
int main() {
std::vector<int> sample = {1, 2, 3};
std::cout << "要素数:" << sample.size() << std::endl;
return 0;
}【実行結果】
要素数:3algorithm ライブラリで vector を操作する
vectorの使用時に合わせて利用する便利なのが、algorithmというライブラリです。
algorithmで使用可能なメンバ関数についても、いくつか紹介したいと思います。
find で要素を検索する
配列内に特定の値が含まれるかを確認したい場合に有効なのが、find() です。
findは、指定した配列の範囲内に対象の要素が含まれる場合に、一番初めに一致した要素の場所を示すイテレーターを返却します。
(見つからなかった場合には、vector.end()の結果が返されます)
#include <iostream>
#include <vector>
#include <algorithm>
int main() {
std::vector<int> sample = {1, 2, 3};
auto itr = std::find(sample.begin(), sample.end(), 2);
if (itr != sample.end()) {
std::cout << "指定の値が含まれています" << std::endl;
} else {
std::cout << "指定の値は含まれません" << std::endl;
}
return 0;
}【実行結果】
指定の値が含まれていますsort で要素をソートする
配列内の要素をソートしたい場合に便利なのが、sort()です。
sortを使用すると、対象の範囲内の要素を昇順に並べ替えることができます。
int main() {
std::vector<int> sample = {1, 3, 8, 2, 5};
std::sort(sample.begin(), sample.end());
std::cout << "ソート後:" << std::endl;
for(const auto& num: sample)
std::cout << num << std::endl;
return 0;
}【実行結果】
ソート後:
1
2
3
5
8まとめ
いかがでしたか?今回は、C++で vectorを使用する方法について解説しました。
配列で動的なデータを扱いたい場合に、vectorは非常に役立つ機能です。
ぜひ、この機会に使い方を覚えて、実践で活用してみてください。
C++の勉強方法は?
書籍やインターネットで学習する方法があります。昨今では、YouTubeなどの動画サイトやエンジニアのコミュニティサイトなども充実していて多くの情報が手に入ります。
そして、より効率的に知識・スキルを習得するには、知識をつけながら実際に手を動かしてみるなど、インプットとアウトプットを繰り返していくことが重要です。特に独学の場合は、有識者に質問ができたりフィードバックをもらえるような環境があると、理解度が深まるでしょう。
ただ、C++に限らず、ITスキルを身につける際、どうしても課題にぶつかってしまうことはありますよね。特に独学だと、わからない部分をプロに質問できる機会を確保しにくく、モチベーションが続きにくいという側面があります。独学でモチベーションを維持する自信がない人にはプログラミングスクールという手もあります。費用は掛かりますが、その分スキルを身につけやすいです。しっかりと知識・スキルを習得して実践に活かしたいという人はプログラミングスクールがおすすめです。
プログラミングスクールならテックマニアがおすすめ!
ITスキル需要の高まりとともにプログラミングスクールも増えました。しかし、どのスクールに通うべきか迷ってしまう人もいるでしょう。そんな方にはテックマニアをおすすめします!これまで多くのITエンジニアを育成・輩出してきたテックマニアでもプログラミングスクールを開講しています。
<テックマニアの特徴>
・たしかな育成実績と親身な教育 ~セカンドキャリアを全力支援~
・講師が現役エンジニア ~“本当”の開発ノウハウを直に学べる~
・専属講師が学習を徹底サポート ~「わからない」を徹底解決~
・実務ベースでスキルを習得 ~実践的な凝縮カリキュラム~
このような特徴を持つテックマニアはITエンジニアのスタートラインとして最適です。
話を聞きたい・詳しく知りたいという方はこちらからお気軽にお問い合わせください。