配列とベクトル:導入の類似点と相違点[終了]


111

C ++の配列とベクトルの違いは何ですか?違いの例としては、ライブラリ、象徴性、能力などがあります。

アレイ

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

— C ++ Pocketリファレンス

ベクター

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

— C ++クックブック


最も基本的な違い:ベクトルが適切な選択である目的があります。
Jerry Coffin

1
「網羅的」と「簡潔」は直交しています。つまり、ないだけではないではない他を意味するものではありますが、彼らも同じ規模ではありません。
オービットの

2
私が探している情報に近い質問をする人々に本当に腹を立てています。これは頻繁に発生します。
ロバートタムリン

回答:


142

配列:

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

std::vector

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

配列の「現代的な代替手段」も考慮してください- std::array; 私はすでに述べた別の答えの違いをstd::vectorしてstd::array、あなたはそれを見てしたいことがあります。


1
@MatteoItalia、ありがとうございます。1つまたは2つの参照がいいでしょう。
トランコット2013

1
@Trancot:良いC ++の本なら何でもいい。
Matteo Italia

6
@Trancot:私は本当にあなたにもっと良いリファレンスを与えることはできません-この投稿で強調されている違いはスタンダードの多くの異なる部分から来ており、良いC ++マニュアルの助けを借りてよりよく理解されます。
Matteo Italia

そのような広範囲にわたる記述の例は素晴らしいでしょう!
carloswm85

26

配列はC ++の非常に低レベルの構成体であり、「ロープを学習する」ときはできるだけそれらに近づかないようにしてください。BjarneStroustrupもこれを推奨しています(彼はC ++の設計者です)。

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


1
アプリケーションプログラムインターフェイス:(en.wikipedia.org/wiki/API)。これは、ソフトウェアエンティティ(パッケージ、ライブラリ、オペレーティングシステム)へのエントリポイントのコレクションです。一部のAPIには、strcat(char * dst、char * src)のようなエントリポイントがあります。dstとsrcは、文字の配列として扱われます(関数のシグネチャは文字へのポインターを意味します)。
JohnKällén2013

11

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

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);
...

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

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.