web-dev-qa-db-ja.com

std :: vector vs. std :: list vs. std :: slistの相対的なパフォーマンス?

リスト要素へのランダムアクセスが必須ではない単純なリンクリストの場合、_std::list_の代わりに_std::vector_を使用することに大きな利点(パフォーマンスまたはその他)がありますか?逆方向のトラバーサルが必要な場合、要素を反復処理する前にリストを_std::slist_およびreverse()を使用する方が効率的ですか?

49
An̲̳̳drew

単にいいえ。リストにはベクターに勝る利点がありますが、シーケンシャルアクセスはそれらの1つではありません。それがあなたのしていることなら、ベクターの方が優れています。

ただし、ベクトルは、特に中央に挿入する場合、リストよりも要素を追加する方が高価です。

これらのコレクションがどのように実装されるかを理解してください。ベクトルはデータのシーケンシャル配列であり、リストはデータと次の要素へのポインターを含む要素です。これを理解すると、リストが挿入に適し、ランダムアクセスに悪い理由を理解できます。

(したがって、ベクトルの逆方向の反復は順方向の反復とまったく同じです-反復子は毎回データ項目のサイズを減算するだけで、リストはポインターを介して次の項目にジャンプする必要があります)

12
gbjbaanb

トピックに関するいくつかの厳密なベンチマーク: http://baptiste-wicht.com/posts/2012/12/cpp-benchmark-vector-list-deque.html

他の人が指摘しているように、連続したメモリストレージは、ほとんどの場合std :: vectorの方が優れていることを意味します。少量のデータ(すべてがキャッシュに収まる場合)および/または消去と再挿入が頻繁に行われる場合を除き、std :: listを使用する正当な理由はほとんどありません。複雑さの保証は、キャッシュとメインメモリの速度(200倍)の違いと、連続したメモリアクセスがキャッシュの使用に与える影響のため、実際のパフォーマンスとは関係ありません。 Chandler Carruth(google)がこの問題について話しているのをご覧ください: https://www.youtube.com/watch?v=fHNmRkzxHWs

そして、マイクアクトンのデータ指向設計についてはこちらをご覧ください: https://www.youtube.com/watch?v=rX0ItVEVjHc

4
metamorphosis

後方トラバーサルが必要な場合、slistがデータ構造になることはほとんどありません。

従来の(二重に)リンクされたリストは、リスト内のどこでも一定の挿入および削除時間を提供します。ベクトルは、リストの最後にある一定の時間の挿入と削除のみを提供します。ベクターの場合、挿入と削除の時間は、終了以外のどこでも線形です。これがすべてではありません。一定の要因もあります。ベクトルは、コンテキストに応じて長所と短所がある、より単純なデータ構造です。

これを理解する最良の方法は、それらの実装方法を理解することです。リンクリストには、各要素の次と前のポインターがあります。ベクトルには、インデックスでアドレス指定された要素の配列があります。このことから、ベクトルのみが効率的なランダムアクセスを提供できる一方で、両方が効率的な前方および後方トラバーサルを実行できることがわかります。また、リンクリストのメモリオーバーヘッドは要素ごとですが、ベクトルの場合は一定です。また、2つの構造で挿入時間が異なる理由もわかります。

4
janm

費用の詳細については、次の質問を参照してください。
標準コンテナの複雑性保証とは

Slistがあり、今度は逆の順序でトラバースする場合、どこにでもリストするようにタイプを変更してみませんか?

2
Martin York