web-dev-qa-db-ja.com

QVectorとQList

反復する必要がある整数のリストがありますが、配列は不十分です。 vectorslistsの違いは何ですか。タイプを選択する前に知っておく必要があることはありますか?

明確にするために、私はQTのドキュメントを読みましたが、これは私が知っている範囲です:

QList<T>QLinkedList<T>、およびQVector<T>は同様の機能を提供します。概要は次のとおりです。

  • ほとんどの場合、QListが適切なクラスです。インデックスベースのAPIは、QLinkedList'sイテレータベースのAPIよりも便利であり、通常、アイテムをメモリに格納する方法のため、QVectorよりも高速です。また、実行可能ファイルのコードが少なくなります。
  • リストの真ん中に一定時間の挿入が保証され、インデックスではなくアイテムへのイテレータが保証されている実際のリンクリストが必要な場合は、QLinkedListを使用します。
  • アイテムが隣接するメモリ位置を占めるようにする場合は、QVectorを使用します。
67
jcuenod

名前から推測できるように、QVectorstd::vectorにほとんど類似しています。 QListは、boost::ptr_dequeと明らかに関連しているにもかかわらず、std::listに近い。オブジェクトを直接保存するのではなく、オブジェクトへのポインタを保存します。両端での迅速な挿入のすべての利点が得られ、再割り当てにはコピーコンストラクターではなくポインターのシャッフルが含まれますが、実際のstd::dequeまたはstd::vectorの空間的局所性は失われ、多くのヒープ割り当てが得られます。小さなオブジェクトのヒープ割り当てを回避し、空間的な局所性を取り戻すための意思決定がありますが、私が理解していることから、それはintより小さいものにのみ適用されます。

QLinkedListstd::listに類似しており、すべての欠点があります。一般的に言えば、これはコンテナの最後の選択です。

QTライブラリはQListオブジェクトの使用を非常に優先しているため、独自のコードでそれらを使用すると、不必要な面倒な作業を避けることができます。余分なヒープの使用と実際のデータのランダムな配置は、状況によっては理論的には害を及ぼす可能性がありますが、多くの場合気付かないことがあります。したがって、プロファイリングでQListへの変更が提案されるまで、QVectorを使用することをお勧めします。連続した割り当てが重要であると思われる場合[読む:T[]]の代わりにQList<T>を期待するコードとインターフェイスしているので、QVectorですぐに開始することもできますバット。


コンテナ全般について質問し、QTドキュメントを参照として使用した場合、上記の情報はあまり役に立ちません。

std::vectorは、サイズを変更できる配列です。すべての要素は隣り合わせに保存され、個々の要素にすばやくアクセスできます。欠点は、挿入が一方の端でのみ効率的であることです。中間または最初に何かを配置する場合、他のオブジェクトをコピーしてスペースを空ける必要があります。 big-oh表記では、最後の挿入はO(1)、それ以外の場所への挿入はO(N)、ランダムアクセスはO(1)です。

std::dequeも同様ですが、オブジェクトが互いに隣り合って保存されることを保証せず、両端での挿入をO(1)にできます。また、一度に割り当てるメモリのチャンクも小さくする必要がありますが、これは重要な場合があります。ランダムアクセスはO(1)で、中央への挿入はO [N)です。vectorと同じです。空間的局所性はstd::vectorよりも劣りますが、オブジェクトクラスター化される傾向があるため、いくつかの利点が得られます。

std::listはリンクリストです。 3つの標準シーケンシャルコンテナの中で最も多くのメモリオーバーヘッドが必要ですが、どこにでも高速に挿入できます...挿入する必要がある場所が事前にわかっている場合。個々の要素へのランダムアクセスは提供されないため、O(N)で反復する必要があります。ただし、実際の挿入はO(1)です。 std::listの最大の利点は、それらをすばやくスプライスできることです。値の範囲全体を別のstd::listに移動すると、操作全体がO(1)になります。また、リストへの参照を無効にすることは非常に難しく、これは重要な場合があります。

一般的な規則として、std::dequeよりstd::vectorを好みます。ただし、生の配列を予期するライブラリにデータを渡す必要がある場合を除きます。 std::vectorは連続することが保証されているため、&v[0]はこの目的で機能します。 std::listを最後に使用したときのことは覚えていませんが、参照が有効であり続けるための強力な保証人が必要だったので、ほぼ確実でした。

114

QVectorstd::vectorに似ています。 QLinkedListstd::listに似ています。 QListはインデックスベースのベクトルですが、メモリ位置は保証されません(std::dequeなど)。

11
Naszta

QtList docから:

  • ほとんどの場合に使用されるQList。数千のアイテムを含む構造の場合、中央への効率的な挿入を可能にし、インデックス付きアクセスを提供します。 prepend()およびappend()は、内部配列の両端にメモリが事前に割り当てられているため、非常に高速です。 _QList<T>_は、タイプTのポインターの配列です。TがポインターまたはQt共有ライクポインタータイプを持っている場合、オブジェクトは配列に直接格納されます

  • QVectorは、QVectorがそのためにメモリを割り当てるため、ポインターよりも大きいサイズの新しいアイテムのappend()またはinsert()が多数ある場合に優先される単一のヒープ割り当てのアイテム。 QListの場合、新しいアイテムの追加の挿入には、ヒープ上の新しいアイテムのメモリ割り当てが必要です。つまり、アイテムを隣接するメモリ位置に配置する場合、またはアイテムがポインターよりも大きく、挿入時にヒープに個別に割り当てるオーバーヘッドを回避する場合は、QVectorを使用します。

2
kiriloff