web-dev-qa-db-ja.com

配列とベクトル:入門の類似点と相違点

C++の配列とベクトルの違いは何ですか?違いの例には、ライブラリ、シンボリズム、能力などが含まれます。

アレイ

配列には、特定のタイプの特定の数の要素が含まれます。コンパイラーは、プログラムのコンパイル時に必要なスペースを確保できるように、定義時に配列に含める要素のタイプと数を指定する必要があります。コンパイラーは、プログラムのコンパイル時にこの値を決定できなければなりません。配列が定義されたら、インデックスとともに配列の識別子を使用して、配列の特定の要素にアクセスします。 [...]配列のインデックスはゼロです。つまり、最初の要素のインデックスは0です。このインデックススキームは、C++でのポインターと配列間の密接な関係、および言語がポインター演算用に定義する規則を示しています。

— C++ポケットリファレンス

ベクター

ベクトルは、配列スタイルのoperator[]ランダムアクセスを提供する動的にサイズ設定されたオブジェクトのシーケンスです。メンバー関数Push_backは、コピーコンストラクターを介して引数をコピーし、そのコピーをベクトルの最後のアイテムとして追加し、そのサイズを1増やします。 pop_backは、最後の要素を削除することにより、まったく逆の処理を行います。ベクターの末尾からのアイテムの挿入または削除には一定の時間がかかり、他の場所からの挿入または削除には直線的な時間がかかります。これらはベクターの基本です。彼らにはもっとたくさんあります。ほとんどの場合、Cスタイルの配列よりもベクトルを最初に選択する必要があります。まず第一に、それらは動的にサイズ調整されます。つまり、必要に応じて成長できます。 C配列の場合のように、最適な静的サイズを見つけるためにあらゆる種類の調査を行う必要はありません。ベクトルは必要に応じて大きくなり、必要に応じて手動で大きくまたは小さくサイズ変更できます。次に、ベクターはatメンバー関数(ただしoperator[]ではない)で境界チェックを提供します。そのため、プログラムがクラッシュしたり、さらに悪い状態で実行を継続するのではなく、存在しないインデックスを参照する場合、何かを実行できます。

— C++クックブック

98
Trancot

配列:

  • 組み込みの言語構成体です。
  • c89からほとんど変更されていません。
  • 要素の連続したインデックス可能なシーケンスを提供する;余計なものはありません。
  • 固定サイズです。 C++で配列のサイズを変更することはできません(PODの配列で、mallocで割り当てられている場合を除く)。
  • それらのサイズは、動的に割り当てられない限り、コンパイル時の定数でなければなりません。
  • 宣言するスコープに応じて、ストレージスペースを使用します。
  • 動的に割り当てられる場合は、明示的に割り当てを解除する必要があります。
  • 動的に割り当てられる場合、ポインタを取得するだけで、サイズを決定することはできません。それ以外の場合は、sizeofを使用できます(そのため、一般的なイディオムsizeof(arr)/sizeof(*arr)。ただし、ポインターで不注意に使用すると暗黙のうちに失敗します)。
  • ほとんどの場合、自動的にポインターに減衰します。特に、これは、それらを関数に渡すときに発生します。通常、サイズに別のパラメーターを渡す必要があります。
  • 関数から返すことはできません。
  • 直接コピー/割り当てすることはできません。
  • オブジェクトの動的配列には、すべての要素を最初に構築する必要があるため、デフォルトのコンストラクターが必要です。

std::vector

  • テンプレートクラスです。
  • c ++のみの構成体です。
  • dynamic array;として実装されます;
  • 動的に増減します。
  • 破壊時に解放されるメモリを自動的に管理します。
  • (値によって)関数に渡したり、関数から返すことができます。
  • コピー/割り当て可能(これにより、保存されているすべての要素のディープコピーが実行されます)。
  • ポインターに減衰しませんが、データへのポインターを明示的に取得できますcan&vec[0]は期待どおりに動作することが保証されています);
  • 常に内部動的配列とともに、そのsize(現在格納されている要素の数)およびcapacity(要素の数は現在割り当てられているブロックに保存できます);
  • 内部動的配列は、オブジェクト自体(いくつかの「ブックキーピング」フィールドを含む)内では割り当てられませんが、関連するテンプレートパラメーターで指定されたアロケーターによって動的に割り当てられます。デフォルトでは、実際のオブジェクトがどのように割り当てられているかに関係なく、フリーストア(いわゆるヒープ)からメモリを取得します。
  • このため、小さな、短命のローカルアレイの「通常の」アレイよりも効率が低い場合があります。
  • 再割り当て時、オブジェクトはcopied(C++ 11では移動);
  • 格納されるオブジェクトのデフォルトコンストラクターは不要です。
  • いわゆるSTLの残りの部分とよりよく統合されます(これはbegin()/end()メソッド、通常のSTL typedefs、...を提供します)

また、配列の「最新の代替」を検討してください-std::array; 別の答えstd::vectorstd::arrayの違いで説明したので、ご覧ください。

125
Matteo Italia

C++では配列は非常に低レベルの構造であるため、「ロープを学ぶ」ときにはできるだけ配列から遠ざけるようにする必要があります。

ベクトルは、配列と同じパフォーマンスに非常に近くなりますが、非常に多くの便利さと安全機能を備えています。おそらく、生の配列を扱うAPIに接続するとき、または独自のコレクションを構築するときに、配列の使用を開始します。

23
John Källén

これらの参照はあなたの質問にほとんど答えました。簡単に言えば、配列のサイズは固定ですが、ベクトルの長さは動的です。配列を使用する場合、宣言時にサイズを指定します。

int myArray[100];
myArray[0]=1;
myArray[1]=2;
myArray[2]=3;

ベクトルの場合は、宣言して要素を追加するだけです

vector<int> myVector;
myVector.Push_back(1);
myVector.Push_back(2);
myVector.Push_back(3);
...

時には、必要な要素の数がわからないので、そのような状況ではベクトルが理想的です。

9
Nicolas Brown