C++のvectorを復習する

1. はじめに

 C++のvectorは、可変長のデータを便利に取り扱えるため、非常に便利である。ここでは、vectorの使い方を簡単に記す。

2 vectorとは

2.1 概略

 配列の表現方法には、固定長と可変長がある。固定長とは、データサイズが固定であるため、実行時にサイズ変更することができない(例:int data[10])。一方、可変長では、プログラム実行時にデータサイズを自由に変更できる。その場合は、vectorなどを使用する

 可変長のデータを取り扱う場合には、map、mallocなどを使用する方法もある。

2.2 vectorとは

 vectorとは、C++の可変長データを取り扱うことができるデータ構造のことである。

2.2.1 メリット:操作が簡単

 vectorのメリットは、データの追加・修正などの操作が簡単にできることである。また、使用方法も従来の配列と同様のアクセスができる。

2.2.2 デメリット:再割り当てに時間がかかる

 もちろんデメリットも存在する。例えば、vectorで予め確保した量を超えたサイズとなる場合は、再割り当てにO(n)のオーバーヘッドがかかる。どうやらvectorは、メモリが不足する場合は、新しい場所にコピーをするようだ。そのため、速度的な問題は気にする必要がある。

2.3 vectorの使用例

 下記にvectorの使用例を示す。

#include <iostream>
#include <vector>
int main()
{
    //vector<int>型の可変長データを宣言
    std::vector<int> vec;

    //vectorに10を代入する
    vec.push_back(10);

    //vectorに100を代入する
    vec.push_back(100);

    //vectorの要素数を取得する
    int size = vec.size();

    //要素数分繰り返す
    for (int i = 0; i < size; i++) {
        //中身を表示する
        std::cout << vec[i] << std::endl;
    }
}

 上記は、vectorの使用例を示したものである。下記に処理をまとめる。
(1) vector<int>型のデータのvecを宣言する
(2) vecに10と100の数値を代入する。
(3) vecの要素数を取得する
(4) vecの要素数分繰り返し、中身を表示する

 このように、vectorでデータの操作が簡単に実施できる。

3. vectorの使用方法

 ここでは、vectorの使用方法をまとめる。

 vectorは下記のヘッダをインクルードして使用する。
 

#include <vector>

3.1 vectorの宣言

 vectorの宣言は、以下のように記述する。

//vectorの定義
std::vector<データ型> 変数名

 データ型には、任意のデータ型(int, double, 構造体)などを入れることができる。実際の記述例は、以下である。

//int型の可変長データvecの宣言
std::vector<int> vec;

//double型の可変長データvecの宣言
std::vector<double> vec;

//構造体の可変長データvecの宣言
std::vector<DATA> vec;

 宣言は見慣れないかもしれないが、簡単である。

3.2 データの代入

 データの代入には、push_backを使用する。

3.2.1 push_back(末尾に追加)

 データの末尾に代入するには、push_backを使用する。

std::vector<int> vec;
//10を代入する
vec.push_back(10);

std::vector<double> vec;
//10.4を代入する
vec.push_back(10.4);

 上記の例は、push_backを使用して、データ型に合ったデータを設定する。

3.2.2 insert(任意の位置に追加)

 任意の位置にデータを追加するには、insertを使用する。

//定義:
insert(イテータの位置, 値);

std::vector<int> vec = {1, 2, 3, 4, 5};

//3個目の位置に値6を挿入
vec.insert(vec.begin() + 2, 100);

 上記は、insertの使用例である。insertの第一引数には、iteratorを渡す。iteratorの先頭を表すbegin()を入れている。例では、その2個先とするため、+2で3番目となる。

3.3 データの参照

 データの参照は、普通の配列と変わらない。

std::vector<int> vec = {1, 2, 3, 4};

//0番目を表示する
std::cout << vec[0] << std::endl;

 上記の例は、データの参照方法である。ここでは、0番地である1を表示している。例からわかる通り、固定長の配列と何ら変わりない。

3.4 データの要素数の取得

 データの要素数を取得するには、sizeを使用する。

std::vector<int> vec = {1, 2, 3, 4};
//要素数を取得する
std::cout << vec.size() << std::endl;

 上記のように記述することでvectorの要素数を取得することができる。

3.5 繰り返し

 vectorの中身を繰り返す方法は以下の通りである。

3.5.1 sizeでループする

 先ほどのsizeでループする例で考える。

std::vector vec = {1, 2, 3, 4};
//要素数分繰り返す
for (int i = 0; i < vec.size(); i++){
  std::cout << vec[i] << std::endl;
}

3.5.2 iteratorを使用する

 iteratorを使用してループすることもできる。

std::vector vec = {1, 2, 3, 4};
// ベクターの要素をイテレータを使用して繰り返す
for(auto it = vec.begin(); it != vec.end(); it++) {
    std::cout << *it << std::endl;
}

 この例は、iteratorを使用してデータを繰り返す例である。イテレータを使用しても配列にアクセスできる。

3.5.3 範囲ベースの繰り返し

 範囲ベースの繰り返しもすることができる。

std::vector vec = {1, 2, 3, 4};
for (auto tmp : vec) {
    std::cout << tmp.second(); << std::endl;
}

 このように、範囲ベースでvectorを繰り返すこともできる。

3.6 ペアを使用する

 std::pairとすることで、key:valueという形でvectorを使用することができる。

std::vector<std::pair<int, std::string>> vec;

vec.push_back({1, "Apple"});
vec.push_back({2, "Banana"});
vec.push_back({3, "Cherry"});
for(const auto& pair : vec) {
    std::cout << pair.first << ": " << pair.second << "\n";
}

 上記の例は、keyに数字、valueに文字列のペアとした配列である。std::pairを使用することで、ペアとして取り扱うこともできる。

3.7 データの末尾を削除する

 データの末尾を削除する場合は、pop_backを使用する。

#include <iostream>
#include <vector>

int main() {
    std::vector<int> vec = {1, 2, 3, 4, 5};

    // ベクタが空でないことを確認
    if (!vec.empty()) {
        vec.pop_back(); // 末尾の要素を削除
    }

    // 結果を表示
    std::cout << "Vector after pop_back: ";
    for(int i : vec) {
        std::cout << i << " ";
    }
    std::cout << std::endl;

    return 0;
}

 注意点は、vectorが空の状態で実行しないと未定義動作となる。

4. 終わりに

 今回は、C++のvectorを使用方法を復習した。vectorを使用できると、プログラムがスムーズに組めるようになるので、気になった方は調べてみると良いと思う。


この記事が気に入ったらサポートをしてみませんか?