C++
 Computer >> コンピューター >  >> プログラミング >> C++

C++のvector::resize()とvector::reserve()の違いとは?使い方を徹底解説


std::vectorは動的配列と同じように、要素の挿入や削除が行われるたびにサイズを自動的に調整できるコンテナで、ストレージの管理はvector自身が担います。

vector::resize()とvector::reserve()の最も大きな違いは、resize()はベクターのサイズ(要素数)を実際に変更するのに対し、reserve()はサイズをまったく変更しないという点です。reserve()は「少なくとも指定した個数の要素を、メモリの再割り当てなしで格納できるようにする」ためだけに使われます。一方、resize()では指定した値が現在の要素数より小さい場合、メモリが縮小され余分な領域は取り除かれます。

resize()とreserve()の比較一覧

項目resize()reserve()
size()(要素数)指定した値に変更される変わらない
capacity()(確保容量)必要に応じて拡張される指定値以上に確保される
新規要素の生成ある(デフォルト値で初期化)ない
既存要素の削除ある(縮小時)ない

vector::resize()

vector::resize(n)は、ベクターの要素数をnに変更します。nが現在の要素数より大きい場合は、不足分の要素がデフォルト初期化されて末尾に追加され、小さい場合は末尾から余分な要素が削除されます。

サンプルプログラムの概要

  • vector<int>型の変数vとイテレータit、整数c(選択肢)およびi(挿入する値)を宣言します。
  • whileループでメニューを表示し、switch文により次の操作を選択できます。
    1:size()で現在の要素数を表示
    2:push_back()で値を追加
    3:resize(4)でベクターのサイズを4に変更
    4:イテレータですべての要素を表示
    5:exit()で終了

C++コード例

#include <iostream>
#include <vector>
using namespace std;
int main() {
    vector<int> v;
    vector<int>::iterator it;
    int c, i;
    while (1) {
        cout << "1.Size of the Vector" << endl;
        cout << "2.Insert Element into the Vector" << endl;
        cout << "3.Resize the vector" << endl;
        cout << "4.Display by Iterator" << endl;
        cout << "5.Exit" << endl;
        cout << "Enter your Choice: ";
        cin >> c;
        switch(c) {
            case 1:
                cout << "Size of Vector: ";
                cout << v.size() << endl; // ベクターのサイズを表示
                break;
            case 2:
                cout << "Enter value to be inserted: ";
                cin >> i;
                v.push_back(i); // 値を追加
                break;
            case 3:
                cout << "Resize the vector elements:" << endl;
                v.resize(4); // ベクターのサイズを4に変更
                break;
            case 4:
                cout << "Displaying Vector by Iterator: ";
                for (it = v.begin(); it != v.end(); it++) { // 全要素を表示
                    cout << *it << " ";
                }
                cout << endl;
                break;
            case 5:
                exit(1);
                break;
            default:
                cout << "Wrong Choice" << endl;
        }
    }
    return 0;
}

実行例

Enter your Choice: 1
Size of Vector: 0
Enter your Choice: 2
Enter value to be inserted: 1
(以降、同様に 2・4・5・5 の順に挿入)
Enter your Choice: 4
Displaying Vector by Iterator: 1 2 4 5 5
Enter your Choice: 3
Resize the vector elements:
Enter your Choice: 4
Displaying Vector by Iterator: 1 2 4 5

この実行例では、最初に5つの値(1, 2, 4, 5, 5)を追加していますが、resize(4)を呼び出した後は要素数が4に減り、末尾の「5」が削除されています。このようにresize()は要素そのものを追加・削除する点がポイントです。なお、resize()で現在の要素数より大きい値を指定した場合、新しく追加されるint型の要素は0で初期化されます。

vector::reserve()

vector::reserve(n)は、「少なくともn個の要素を、メモリを再割り当てせずに格納できるように」内部バッファ(capacity)を事前に確保します。ただし、実際の要素数であるsize()は一切変わりません。今後大量のpush_back()を行うことが分かっている場合に、不要な再割り当てやコピーのコストを回避するために使います。

サンプルプログラムの概要

  • resize()の例と同様に、メニュー形式でベクターを操作します。
  • 選択肢3ではreserve(100)を呼び出し、100個分の容量を確保します。
  • その他の操作(サイズ表示・値の挿入・イテレータによる表示・終了)はresize()の例と同じです。

C++コード例

#include <iostream>
#include <vector>
using namespace std;
int main() {
    vector<int> v;
    vector<int>::iterator it;
    int c, i;
    while (1) {
        cout << "1.Size of the Vector" << endl;
        cout << "2.Insert Element into the Vector" << endl;
        cout << "3.Reserve the vector" << endl;
        cout << "4.Display by Iterator" << endl;
        cout << "5.Exit" << endl;
        cout << "Enter your Choice: ";
        cin >> c;
        switch(c) {
            case 1:
                cout << "Size of Vector: ";
                cout << v.size() << endl;
                break;
            case 2:
                cout << "Enter value to be inserted: ";
                cin >> i;
                v.push_back(i);
                break;
            case 3:
                cout << "Reserve the vector elements:" << endl;
                v.reserve(100); // 100個分の容量を確保
                break;
            case 4:
                cout << "Displaying Vector by Iterator: ";
                for (it = v.begin(); it != v.end(); it++) {
                    cout << *it << " ";
                }
                cout << endl;
                break;
            case 5:
                exit(1);
                break;
            default:
                cout << "Wrong Choice" << endl;
        }
    }
    return 0;
}

実行例

Enter your Choice: 1
Size of Vector: 0
Enter your Choice: 2
Enter value to be inserted: 1
(以降、同様に 2・3・4・5 の順に挿入)
Enter your Choice: 3
Reserve the vector elements:
Enter your Choice: 4
Displaying Vector by Iterator: 1 2 3 4 5

注目すべきは、reserve(100)を実行してもsize()は5のまま変化せず、表示される要素も「1 2 3 4 5」のままだという点です。確保されたのはあくまで「容量(capacity)」であり、v.capacity()を確認すると100以上の値になっています。

まとめ

  • resize():要素数を直接変更する。拡大時は新しい要素が生成され、縮小時は既存の要素が削除される。
  • reserve():容量だけを事前に確保する。要素数も中身も変わらない。
  • 将来追加する要素数があらかじめ分かっている場合はreserve()でパフォーマンスを改善し、実際に要素数を揃えたい場合はresize()を使う、と使い分けるとよいでしょう。
  1. C++のstd::vector::resize()とstd::vector::reserve()の違いを徹底解説

    std::vector(ベクター)は動的配列のように振る舞い、要素の挿入や削除に応じて自動的にサイズを調整し、メモリ(ストレージ)もコンテナ自身が管理してくれる非常に便利なコンテナです。 しかし、「要素数そのものを変更したい」のか「メモリを事前に確保したい」のかによって、使うべき関数は異なります。resize() と reserve() の主な違いは次の通りです。 resize(): ベクトルのサイズ(要素数)そのものを変更します。指定した数が現在より小さい場合は余分な領域と要素が削除され、大きい場合は新しい要素が追加されます。 reserve(): サイズは一切変更せず、少なくとも指定した

  2. C++の型推論とは?autoキーワードの基本と使い方をわかりやすく解説

    型推論(Type Inference)とは、プログラミング言語において式のデータ型を自動的に判別する機能のことです。この機能は、強い静的型付けを持つ一部の言語に備わっています。 C++では、C++11で追加されたautoキーワードを使うことで、自動的な型推論が可能になります。これにより、開発者は複雑な型名を明示的に書く必要がなくなり、コードがシンプルで読みやすくなります。 autoキーワードの活用例 たとえば、vectorの要素を走査するイテレータを作成したい場合、従来は std::vector<int>::iterator という長い型名を記述する必要がありました。しかし、aut