2009-05-25 14 views
4

私が必要とするのは、動的に成長するアレイです。私はランダムアクセスは必要ありません。私はいつも最後に挿入し、最初から最後まで読みます。ベクトル上のスライスの利点?

私は必要なだけのものを提供するので、スライスが最初の選択であるようです。しかし、私はベクトルの代わりにスライスを使うことでどんな利益を得るのか分かりません。さらに、私がSTLについて読んだいくつかの資料では、「ベクトルは一般的に、要素へのアクセスとシーケンスの最後からの要素の追加または削除に最も効率的です。したがって、私の質問は:私のニーズのために、スライスは本当にベクトルよりも良い選択ですか?前もって感謝します。

+3

slistはsgi STLディストリビューションの一部ですが、C++標準ライブラリの一部ではありません。 C++の0x/C++ 1x(次のC++バージョン)ではstd :: forward_listがあります。 –

+0

ありがとう、私はまた今すぐそれを学んだ。 –

+0

STLにstd :: list クラスもあります。 – mmmmmmmm

答えて

13

はじめに、slistは非標準です。

あなたの選択に応じて、リンクされたリストはベクトルよりも遅くなり、カウントされます。これには2つの理由があります。

  1. まず、キャッシュのローカリティ。ベクトルはその要素をRAMに直線的に格納し、キャッシングとプリフェッチを容易にします。
  2. 第2に、リンクリストへの追加には大きなオーバーヘッドを追加する動的な割り当てが必要です。対照的に、ほとんどの場合、ベクトルはではなく、はメモリを割り当てる必要があります。

ただし、std::dequeはおそらくさらに高速になります。 In-depth performance analysisは、その逆のバイアスにもかかわらず、その改善された(チャンクされた)メモリ割り当て戦略のために、性能において(ランダムアクセスが必要でない場合)std::vectorよりほぼ常に優れていることを示している。

+0

あなたはスライスが遅くなると思いますが、これは神秘的な(そしてすべてのアプリケーションに適用可能な)パフォーマンス評価はどこにありますか? http://www.sgi.com/tech/stl/Deque.htmlでは、「デキュがベクトルと異なる主な方法は、デキュールがシーケンスの開始時に要素の一定時間の挿入と削除もサポートすることです。しかしOPは明示的に彼が最初に挿入や削除をしていないと言いました。 –

+0

また、私はあなたがスライスのためのドキュメントを見つけることができなかったと信じることは難しいと思う。 –

+0

マシュー:罪を犯したとして罪を犯しました:私は怠け者でした。あなたの告発について:SGIの記事は単に時代遅れであると言います。それは真実だと考えられていましたが、ベンチマークでは、ベクトルの典型的な使用法でも 'deque'が' vector'よりも優れていることを単に示しています。関連する分析をリンクしました。 –

3

はい、常に最初から最後まで読んでいる場合は、slist(リンクリスト)のように聞こえます。可能な例外は、大量の要素を同時に最後に挿入する場合です。それでは、reserveを適切に使うとベクタが良くなるかもしれません。

もちろん、プロファイルはアプリケーションの方が適切であることを確認してください。

+0

これは、私が書いた(データでバックアップした)ものとは逆のように聞こえるので、おそらく正しいとは言えません。 –

+0

あなたはスライスに関するデータを提供しておらず、あくまでもあくまでも約束です。また、他の2つの(スライス以外の)構造の比較もあります。 –

+0

もう一度:申し訳ありません。私はちょっとばかげているようですが、私はベンチマークを混乱させました。 –

1

私はstd :: listを "slist"と呼んでいると思います。ベクタは、連続したメモリへの高速ランダムアクセス、保証された連続メモリ、高速シーケンシャル読み込み(IOW、最初から最後まで)が必要な場合に適しています。シーケンスの開始時または終了時にアイテムを高速に(一定時間)挿入または削除する必要がある場合は、リストが良好ですが、ランダムアクセスまたはシーケンシャル読み取りのパフォーマンスは気にしません。

違いの理由は、2が実装される方法です。ベクターはアイテムの配列として内部的に実装されます。アイテムの追加時にサイズ/容量に達すると、再割り当てが必要になります。リストは二重リンクリストとして実装されているため、シーケンシャル読み取りでキャッシュミスが発生する可能性があります。リストのランダムアクセスでは、リスト内の最初(または最後)のアイテムから、要求しているアイテムが見つかるまでスキャンする必要があります。

+0

ちょうど実現、スライス、単一リンクリスト、標準ではない?しかし、HP/SGI STLには表示されます。 –

+0

残念ながら、std :: listは二重にリンクされたリストであり、OPの記述された要件を考えると全く不要です。そうでなければ、私はこれに同意します。 –

2

Matt Austern(「Generic Programming and STL」の著者と一般的なC++達人)は、今後のC++標準に含めるための単独リンクリストの強力な提唱者です。彼のプレゼンテーションhttp://www.accu-usa.org/Slides/SinglyLinkedLists.pptと彼の長い記事http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2543.htmを参照してください。このデータ構造を選択するのに役立つかもしれないトレードオフの議論を含めて、詳細を参照してください。 (現在提案されている名前はforward_listですが、slistはSGIのSTL &他の一般的なライブラリでどのように伝えられていたかです)。

2

私は、std::vectorまたはstd::dequeという仕事をしてくれるという意見を2番目(または多分3番目)にします。私が追加する唯一の事柄は、std::vector<T>std::list<T>の間で決定を導くべき追加の要素です。これらは、Tの特性と、使用する予定のアルゴリズムと関係があります。

最初はメモリオーバーヘッドです。 Std::listはノードベースのコンテナなので、Tがプリミティブ型または比較的小さなユーザー定義型の場合は、ノードベースのリンケージのメモリオーバーヘッドが無視できない場合があります。std::list<int>は少なくとも3 * sizeof(int)の記憶域を使用する可能性があると考えてくださいstd::vectorは小さなヘッダーオーバーヘッドでsizeof(int)のストレージのみを使用します。 Std::dequestd::vectorに似ていますが、小さなオーバーヘッドはNに線形です。

次の問題は、コピー構築のコストです。 T(T const&)がすべて高価な場合は、std::vector<T>をクリアしてください。これは、ベクターのサイズが大きくなるにつれてコピーが多数生成されるためです。これはstd::deque<T>が明確な勝者であり、std::list<T>も候補者です。

通常、コンテナの種類の決定を導く最後の問題は、アルゴリズムがイテレーターの無効化の制約とstd::dequeで機能できるかどうかです。コンテナ要素をたくさん操作する(ソート、途中で挿入する、シャッフルするなど)場合は、順序を操作するためにリンケージポインタをいくつかリセットする必要があるため、std::listに傾けたいと思うかもしれません。

0

std :: deque私には良い仕事のようですね。これは、各 "スラブ"(CPUキャッシュに適している)ごとに連続したメモリ割り当てのようなベクトルのメリットがあり、std :: listのような各要素のオーバーヘッドがなく、セット全体をstd :: vectorとして再割り当てする必要はありませんそうです。 std::deque here

関連する問題