以来
誰もが好む理由std::vector
からstd::deque
?
deque
の要素は、メモリ内で連続しているnotです。 vector
要素は保証されています。したがって、連続した配列を必要とするプレーンなCライブラリとやり取りする必要がある場合、または空間的な局所性に(かなり)関心がある場合は、vector
を好むかもしれません。さらに、追加のブックキーピングがあるため、他の操作はおそらく同等のvector
操作よりも(わずかに)高価です。一方、vector
の多数/大規模なインスタンスを使用すると、不要なヒープフラグメンテーションが発生する可能性があります(new
への呼び出しが遅くなります)。
また、指摘したように StackOverflowの他の場所 には、より良い議論があります: http://www.gotw.ca/gotw/054.htm 。
違いを知るには、deque
の一般的な実装方法を知っておく必要があります。メモリは同じサイズのブロックで割り当てられ、それらは一緒に連鎖されます(配列または場合によってはベクトルとして)。
したがって、n番目の要素を見つけるには、適切なブロックを見つけて、その中の要素にアクセスします。常に2回のルックアップであるため、これは一定の時間ですが、それでもベクトルよりも多くなります。
vector
は、C APIであるか、ポインターと長さを取得できるという点で汎用性が高いため、連続したバッファーが必要なAPIでもうまく機能します。 (したがって、下にベクトルまたは通常の配列を作成し、メモリブロックからAPIを呼び出すことができます)。
deque
の最大の利点は次のとおりです。
これらの2番目はあまり知られていませんが、非常に大きなコレクションサイズの場合:
過去に大きなコレクションを扱っていて、連続モデルからブロックモデルに移行したとき、32ビットシステムでメモリが不足する前に、約5倍のコレクションを保存できました。これは、再割り当ての際に、要素をコピーする前に古いブロックと新しいブロックを実際に保存する必要があるためです。
これをすべて言ったが、「楽観的な」メモリ割り当てを使用するシステムでは、std::deque
で問題が発生する可能性があります。 vector
の再割り当てのために大きなバッファサイズを要求する試みは、おそらくbad_alloc
である時点で拒否されますが、アロケータの楽観的な性質は、常にdeque
によって要求されるより小さなバッファ。これにより、オペレーティングシステムがプロセスを強制終了して、メモリを獲得しようとする可能性があります。どれを選んでも、あまり快適ではないかもしれません。
そのような場合の回避策は、システムレベルのフラグを設定して楽観的な割り当てを無効にするか(常に実行可能であるとは限りません)、メモリを多少手動で管理することです。メモリ使用量などを確認する独自のアロケータを使用します。明らかに理想的ではありません。 (ベクトルを好むという質問に答えるかもしれません...)
Vectorとdequeの両方を複数回実装しました。 dequeは、実装の観点から見ると非常に複雑です。この複雑さは、より多くのコードとより複雑なコードに変換されます。したがって、通常、ベクトルよりも両端キューを選択すると、コードサイズがヒットします。また、コードでベクターが優れているもの(Push_back)のみを使用している場合、わずかな速度低下が発生する可能性があります。
両端キューが必要な場合、dequeが明確な勝者です。ただし、ほとんどの挿入と消去をバックで行う場合は、ベクターが明確な勝者になります。確信が持てない場合は、typedefを使用してコンテナーを宣言し(そのため、簡単に切り替えられます)、測定します。
std::deque
は、連続メモリを保証していません-インデックス付きアクセスの場合は、多少遅いことがよくあります。通常、両端キューは「ベクトルのリスト」として実装されます。
http://www.cplusplus.com/reference/stl/deque/ によると、「dequeはベクターとは異なり、すべての要素が連続したストレージ場所にあるとは限らないため、安全である可能性がなくなります。ポインタ演算によるアクセス。」
両端キューは、もう少し複雑です。これは、一部には必ずしも連続したメモリレイアウトがないためです。その機能が必要な場合は、両端キューを使用しないでください。
(以前、私の答えは標準化の欠如をもたらしました(上記と同じソースから、「異なる方法で特定のライブラリによって両端キューを実装することができます」)が、実際にはほぼすべての標準ライブラリデータ型に適用されます。)
各ケースのパフォーマンステストを行うことをお勧めします。そして、このテストに基づいて決定を下します。
ほとんどの場合、std::deque
よりstd::vector
の方が好きです。
これらのテスト結果(ソースあり)に対応するdequeにベクターを好まないでしょう。
もちろん、アプリ/環境でテストする必要がありますが、要約すると:
Dequeは、その要素へのランダムアクセスを許可するシーケンスコンテナですが、連続したストレージを持つことは保証されていません。
一方では、ベクターは非常に頻繁にdequeよりも単純に高速です。 dequeのすべての機能を実際に必要としない場合は、ベクトルを使用します。
一方で、時々doはベクターが提供しない機能を必要とします。その場合、dequeを使用する必要があります。たとえば、dequeを使用せず、アルゴリズムを大幅に変更せずに、 このコード の書き換えを試みるように、誰にでも挑戦します。