重複の可能性:
両端キューにベクトルを使用することを好む理由
std::vector
が std::deque
よりもはるかに人気があるのはなぜですか。 Dequeは、ルックアップでほぼ同じくらい効率的で、挿入(vector :: reservedなし)でより効率的であり、前面での挿入/削除を可能にします。
ハーブサッターはかつて、 ベクターを使用したい場合はdequeを好む (言い換えれば)を推奨していました。ただし、最近の Writing Modern C++ に関する講演では、std::vector
をデフォルトのコンテナとして考えることを強くお勧めします。 [〜#〜] gotw [〜#〜] 先ほどリンクしたところによると、標準でも同様の表現があります。
この格差の理由はありますか? vector
がより単純でよく知られているというだけですか、それとも技術的な理由がありますか?それとも、vector
はもっとかっこいい名前なのか..?
私は他の人のために話すことはできませんが、私自身のために話すことはできます。
std::deque
について最初に読んだとき、しばらくの間、デフォルトのコンテナとしてだけでなく、ほぼonly私が使用したコンテナ。
それから誰かがその理由について尋ねました、そして私はその長所とそれが事実上すべてに使用するのに最適なコンテナである理由、そしてそれがstd::vector
よりもはるかに用途が広い方法について詳しく説明しました。
幸いなことに、それについての私の決定を疑問視している人は、私がいくつかのテストを行うのに十分説得力がありました。テストの結果、ほぼすべての場合で、std::deque
はstd::vector
よりも遅いことがわかりました。多くの場合、かなりの要因(たとえば、約2)が原因です。実際、私がstd::deque
を使用して記述したコードのうち、std::deque
をstd::vector
に置き換えるだけで、ほんの一握りの場合を除いてスピードアップが得られました。
それ以来、いくつかのケースでstd::deque
を使用していますが、これ以上デフォルトとして扱わないことは間違いありません。単純な事実は、通常の実装では、ほとんどの目的でstd::vector
よりも著しく遅いということです。
ただし、適切な実装があれば、可能性は事実上すべてのstd::vector
とほぼ同等であると合理的に確信していることを付け加えておきます。ケース。ほとんどの場合、漸近的な観点からは間違いなく優れた表現を使用しますが、現実の世界では(多くの目的で)それほどうまく機能しません。
std::vector
は非常によく理解されており、シンプルで、Cと互換性があります(メモリレイアウトとイテレータとしてのポインタの使用の両方の点で)。
一部の操作では、std::deque
よりも効率的です。インデックスによる要素へのアクセスはその一例です。
特定のタスクでは、そのジョブを適切に実行する最も単純なコンテナーを使用するのが理にかなっています。多くの場合、最も単純なコンテナはstd::vector
です。
std::vector
が最も一般的に知られているコンテナクラスであることに加えて、std::deque
に比べていくつかの利点があります。
std::deque
は、std::vector
の場合とは異なり、要素にアクセスするために追加の間接参照を必要とします。std::deque
の場合のイテレータは、std::vector
の場合のようにポインタではなく、スマートポインタである必要があります。std::vector
の要素は連続していることが保証されているため、配列をパラメーターとして受け取るcスタイルの関数と互換性があります。std::deque
は、容量と再割り当ての瞬間を制御するためのサポートを提供しません。特に最後の点は注目に値します。
人々は単純な理由でstd :: dequeよりもstd :: vectorを使用します。それらは多くのCライブラリとインターフェイスし、連続したストレージへのポインタを必要とするパラメータを持つ functions を持ちますが、std :: dequeは保証しません(保証できません)。
もう1つの理由は、std :: dequeに従ってコードをビルドし、要件が変更されて連続アクセスをサポートする必要がある場合、少しリファクタリングを行う必要があることです。
容量 が増加したときに非効率性を克服するために、より効率的なベクトル実装を作成したと著者が主張している ライブラリ が存在することに言及せざるを得ません。
_std::deque
_の構造は少し複雑であるため、ナイーブな反復は_std::vector
_よりもかなり高価になります。再割り当てを伴う_std::vector
_への挿入は、特にreserve()
を使用し、末尾に追加するだけの場合は、大きな問題にはならない傾向があります。また、_std::vector
_の無効化ルールを理解するのは簡単ですが、実際には_std::deque
_の利点は、どちらかの端でのみ挿入/削除するときにオブジェクトが配置されたままになることです(_std::deque
_イテレータは無効化されることに注意してください)挿入が行われる場所に関係なく、挿入のたびに)。 _std:vector
_のもう1つの利点は、値がメモリ内で連続していることを保証することです。これにより、メモリ割り当てが少なくなります。
おそらく、_std::deque
_アルゴリズムの使用は、セグメント化されたシーケンスを使用するように一貫して最適化されており(標準C++ライブラリがこの最適化を行っていることはわかりません)、ユーザーはアルゴリズムを使用して一貫してシーケンスにアクセスしていました(可能な限り)言うまでもなく、アルゴリズムを使用するオプションを検討しているユーザーはごくわずかです)。そうでなければ、_std::deque
_は、その特定のプロパティを利用する場合にのみ、パフォーマンスに関してより良いオプションであると思います(たとえば、オブジェクトは配置されたままで、最後に挿入/削除できます)。ただし、2つの選択肢をプロファイリングする価値はあります。