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

C++のstd::vector::resize()とstd::vector::reserve()の違いを徹底解説

std::vector(ベクター)は動的配列のように振る舞い、要素の挿入や削除に応じて自動的にサイズを調整し、メモリ(ストレージ)もコンテナ自身が管理してくれる非常に便利なコンテナです。

しかし、「要素数そのものを変更したい」のか「メモリを事前に確保したい」のかによって、使うべき関数は異なります。resize()reserve() の主な違いは次の通りです。

  • resize(): ベクトルのサイズ(要素数)そのものを変更します。指定した数が現在より小さい場合は余分な領域と要素が削除され、大きい場合は新しい要素が追加されます。
  • reserve(): サイズは一切変更せず、少なくとも指定した数の要素を格納できる容量(capacity)を事前に確保するだけです。これにより、要素追加時のメモリ再割り当てを回避できます。

resize() と reserve() の比較表

項目resize()reserve()
size(要素数)指定値に変更される変更されない
capacity(容量)必要に応じて拡張される少なくとも指定値になるよう確保
新規要素の初期化行われる(デフォルト値で埋まる)行われない
要素の削除縮小時に末尾から削除される行われない

vector::resize() とは

resize() は、ベクトルが保持する要素数(size)を引数で指定した値に変更するためのメンバ関数です。要素数が増える場合は追加部分がデフォルト初期化され、減る場合は末尾の余分な要素が削除されてメモリも縮小されます。

アルゴリズム

開始
   ベクトル型の変数 v を宣言する
   ベクトル型のイテレータ it を宣言する
   整数型の変数 c と i を宣言する
   while (TRUE) ループ:
      「1.ベクトルのサイズ確認」と表示する
      「2.ベクトルへ要素を挿入」と表示する
      「3.ベクトルをリサイズ」と表示する
      「4.イテレータによる表示」と表示する
      「5.終了」と表示する
      「選択肢を入力してください:」と表示し、c に値を入力する
      switch (c):
         ケース 1:
            「ベクトルのサイズ:」を表示し、size() でサイズを出力する
         ケース 2:
            挿入する値を入力し、push_back() でベクトルに追加する
         ケース 3:
            resize() を呼び出してベクトルをリサイズする
         ケース 4:
            イテレータを使い、begin() から end() まで全要素を表示する
         ケース 5:
            exit() を呼び出してプログラムを終了する
         デフォルト:
            「不正な選択です」と表示する
終了

サンプルコード

#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: 2
Enter value to be inserted: 1
Enter your Choice: 2
Enter value to be inserted: 2
Enter your Choice: 2
Enter value to be inserted: 4
Enter your Choice: 2
Enter value to be inserted: 5
Enter your Choice: 2
Enter value to be inserted: 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
Enter your Choice: 5

この実行例では、まず5つの要素(1, 2, 4, 5, 5)を挿入しています。その後 resize(4) を呼び出すと、要素数が4に縮小され、末尾の余分な要素が削除されて「1 2 4 5」と表示されます。このように resize() はコンテナの中身そのものを書き換えます。

vector::reserve() とは

reserve() は、メモリの再割り当てを発生させずに済むよう、少なくとも指定した数の要素を格納できる容量を事前に確保するためのメンバ関数です。呼び出しても要素数(size)は変化せず、表示される内容にも影響しません。確保されるのはあくまで内部的な「容量(capacity)」だけです。

アルゴリズム

開始
   ベクトル型の変数 v を宣言する
   ベクトル型のイテレータ it を宣言する
   整数型の変数 c と i を宣言する
   while (TRUE) ループ:
      「1.ベクトルのサイズ確認」と表示する
      「2.ベクトルへ要素を挿入」と表示する
      「3.ベクトルの容量を確保」と表示する
      「4.イテレータによる表示」と表示する
      「5.終了」と表示する
      「選択肢を入力してください:」と表示し、c に値を入力する
      switch (c):
         ケース 1:
            「ベクトルのサイズ:」を表示し、size() でサイズを出力する
         ケース 2:
            挿入する値を入力し、push_back() でベクトルに追加する
         ケース 3:
            reserve() を呼び出してベクトルの容量を確保する
         ケース 4:
            イテレータを使い、begin() から end() まで全要素を表示する
         ケース 5:
            exit() を呼び出してプログラムを終了する
         デフォルト:
            「不正な選択です」と表示する
終了

サンプルコード

#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: 2
Enter value to be inserted: 1
Enter your Choice: 2
Enter value to be inserted: 2
Enter your Choice: 2
Enter value to be inserted: 3
Enter your Choice: 2
Enter value to be inserted: 4
Enter your Choice: 2
Enter value to be inserted: 5
Enter your Choice: 3
Reserve the vector elements.
Enter your Choice: 4
Displaying Vector by Iterator: 1 2 3 4 5

この実行例では、5つの要素(1〜5)を挿入した後に reserve(100) を呼び出していますが、直後にイテレータで表示しても内容は「1 2 3 4 5」のままで、要素数は一切変化していません。reserve() は内部バッファの容量を広げるだけで、見た目や中身には何の影響も与えません。なお、v.capacity() を呼び出せば、実際に確保された容量を確認できます。

まとめ

  • resize(n): size を n に変更する。要素の追加・削除・初期化が実際に行われる。
  • reserve(n): capacity を最低 n に確保するだけ。size は不変で、要素は生成されない。
  • 大量の push_back() が予想される場合は、先に reserve() しておくことでメモリ再割り当てのコストを削減でき、パフォーマンスが向上する。
  • 現在の要素数は size()、確保済み容量は capacity() でそれぞれ確認できる。
  1. C++のvector::resize()とvector::reserve()の違いとは?使い方を徹底解説

    std::vectorは動的配列と同じように、要素の挿入や削除が行われるたびにサイズを自動的に調整できるコンテナで、ストレージの管理はvector自身が担います。 vector::resize()とvector::reserve()の最も大きな違いは、resize()はベクターのサイズ(要素数)を実際に変更するのに対し、reserve()はサイズをまったく変更しないという点です。reserve()は「少なくとも指定した個数の要素を、メモリの再割り当てなしで格納できるようにする」ためだけに使われます。一方、resize()では指定した値が現在の要素数より小さい場合、メモリが縮小され余分な領域は

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

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