web-dev-qa-db-ja.com

std :: vectorがstd :: dequeよりもはるかに人気があるのはなぜですか?

重複の可能性:
両端キューにベクトルを使用することを好む理由

std::vectorstd::deque よりもはるかに人気があるのはなぜですか。 Dequeは、ルックアップでほぼ同じくらい効率的で、挿入(vector :: reservedなし)でより効率的であり、前面での挿入/削除を可能にします。

ハーブサッターはかつて、 ベクターを使用したい場合はdequeを好む (言い換えれば)を推奨していました。ただし、最近の Writing Modern C++ に関する講演では、std::vectorをデフォルトのコンテナとして考えることを強くお勧めします。 [〜#〜] gotw [〜#〜] 先ほどリンクしたところによると、標準でも同様の表現があります。

この格差の理由はありますか? vectorがより単純でよく知られているというだけですか、それとも技術的な理由がありますか?それとも、vectorはもっとかっこいい名前なのか..?

51
Karthik T

私は他の人のために話すことはできませんが、私自身のために話すことはできます。

std::dequeについて最初に読んだとき、しばらくの間、デフォルトのコンテナとしてだけでなく、ほぼonly私が使用したコンテナ。

それから誰かがその理由について尋ねました、そして私はその長所とそれが事実上すべてに使用するのに最適なコンテナである理由、そしてそれがstd::vectorよりもはるかに用途が広い方法について詳しく説明しました。

幸いなことに、それについての私の決定を疑問視している人は、私がいくつかのテストを行うのに十分説得力がありました。テストの結果、ほぼすべての場合で、std::dequestd::vectorよりも遅いことがわかりました。多くの場合、かなりの要因(たとえば、約2)が原因です。実際、私がstd::dequeを使用して記述したコードのうち、std::dequestd::vectorに置き換えるだけで、ほんの一握りの場合を除いてスピードアップが得られました。

それ以来、いくつかのケースでstd::dequeを使用していますが、これ以上デフォルトとして扱わないことは間違いありません。単純な事実は、通常の実装では、ほとんどの目的でstd::vectorよりも著しく遅いということです。

ただし、適切な実装があれば、可能性は事実上すべてのstd::vectorとほぼ同等であると合理的に確信していることを付け加えておきます。ケース。ほとんどの場合、漸近的な観点からは間違いなく優れた表現を使用しますが、現実の世界では(多くの目的で)それほどうまく機能しません。

57
Jerry Coffin

std::vectorは非常によく理解されており、シンプルで、Cと互換性があります(メモリレイアウトとイテレータとしてのポインタの使用の両方の点で)。

一部の操作では、std::dequeよりも効率的です。インデックスによる要素へのアクセスはその一例です。

特定のタスクでは、そのジョブを適切に実行する最も単純なコンテナーを使用するのが理にかなっています。多くの場合、最も単純なコンテナはstd::vectorです。

14
NPE

std::vectorが最も一般的に知られているコンテナクラスであることに加えて、std::dequeに比べていくつかの利点があります。

  • 典型的なstd::dequeは、std::vectorの場合とは異なり、要素にアクセスするために追加の間接参照を必要とします。
  • std::dequeの場合のイテレータは、std::vectorの場合のようにポインタではなく、スマートポインタである必要があります。
  • std::vectorの要素は連続していることが保証されているため、配列をパラメーターとして受け取るcスタイルの関数と互換性があります。
  • std::dequeは、容量と再割り当ての瞬間を制御するためのサポートを提供しません。

特に最後の点は注目に値します。

5
Alok Save

人々は単純な理由でstd :: dequeよりもstd :: vectorを使用します。それらは多くのCライブラリとインターフェイスし、連続したストレージへのポインタを必要とするパラメータを持つ functions を持ちますが、std :: dequeは保証しません(保証できません)。

もう1つの理由は、std :: dequeに従ってコードをビルドし、要件が変更されて連続アクセスをサポートする必要がある場合、少しリファクタリングを行う必要があることです。

容量 が増加したときに非効率性を克服するために、より効率的なベクトル実装を作成したと著者が主張している ライブラリ が存在することに言及せざるを得ません。

5
nurettin

_std::deque_の構造は少し複雑であるため、ナイーブな反復は_std::vector_よりもかなり高価になります。再割り当てを伴う_std::vector_への挿入は、特にreserve()を使用し、末尾に追加するだけの場合は、大きな問題にはならない傾向があります。また、_std::vector_の無効化ルールを理解するのは簡単ですが、実際には_std::deque_の利点は、どちらかの端でのみ挿入/削除するときにオブジェクトが配置されたままになることです(_std::deque_イテレータは無効化されることに注意してください)挿入が行われる場所に関係なく、挿入のたびに)。 _std:vector_のもう1つの利点は、値がメモリ内で連続していることを保証することです。これにより、メモリ割り当てが少なくなります。

おそらく、_std::deque_アルゴリズムの使用は、セグメント化されたシーケンスを使用するように一貫して最適化されており(標準C++ライブラリがこの最適化を行っていることはわかりません)、ユーザーはアルゴリズムを使用して一貫してシーケンスにアクセスしていました(可能な限り)言うまでもなく、アルゴリズムを使用するオプションを検討しているユーザーはごくわずかです)。そうでなければ、_std::deque_は、その特定のプロパティを利用する場合にのみ、パフォーマンスに関してより良いオプションであると思います(たとえば、オブジェクトは配置されたままで、最後に挿入/削除できます)。ただし、2つの選択肢をプロファイリングする価値はあります。

5
Dietmar Kühl