QVectorとQList


80

反復する必要のある整数のリストがありますが、配列が不十分です。どのような違いがあるvectorslists、私はタイプを選ぶ前に、私が知っている必要がありますが何ですか?

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

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

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

回答:


122

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

QLinkedListに類似しstd::listており、すべての欠点があります。一般的に言って、これがコンテナの最後の選択になるはずです。

QTライブラリはQListオブジェクトの使用を大いに支持しているため、独自のコードでオブジェクトを支持することで、不必要な面倒な作業を回避できる場合があります。余分なヒープの使用と実際のデータのランダムな配置は、状況によっては理論的には害を及ぼす可能性がありますが、見過ごされがちです。したがってQList、プロファイリングがに変更することを提案するまで使用することをお勧めしQVectorます。連続した割り当てが重要であると予想される場合[読んでください:のT[]代わりにを期待するコードとインターフェースしているQList<T>]、それはまた、QVectorすぐに始める理由になる可能性があります。


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

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

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

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

一般的なルールとして、私が好むstd::dequestd::vector、私は生の配列を期待ライブラリにデータを渡すことができるようにする必要がありますしない限り、。 std::vector連続性が保証されて&v[0]いるため、この目的で機能します。前回使用したのは覚えていませんstd::listが、参照が有効なままであるというより強力な保証が必要だったためです。


FWIW、std :: dequeには、参照に関してかなり良い保証があります。イテレータは簡単に無効になりますが、メンバーへのポインタはデキューの操作に対してかなり堅牢です。
ベン

素晴らしい答え。しかし、私は追加の質問があります:反復するのが速いのはどれですか?オブジェクトのセットがあり、実際には頻繁に挿入または削除されることはありませんが、オブジェクトをできるだけ速く反復する必要があります。どちらが速いですか?
birgersp 2015

良い情報。次のステートメントが最も役立つことがわかりました...「QTライブラリはQListオブジェクトの使用を大いに支持しています」。私のユースケースでは、QListやQListStringが好きなQTableWidgetを扱っています。したがって、ユースケースでQVectorとQListの間の決定を決定するようにします。
パノフィッシュ2015年

1
あなたは実際にベンチマークをstd::dequeしましたstd::vectorか?...あなた驚かれることでしょう
mmutz -マルク・MUTZ

4
QListはデフォルトのコンテナとしては不適切な推奨であるというQt開発者からの苦情を受けて、ドキュメントが更新されていることに注意してください。「QVectorをデフォルトの最初の選択肢にする必要があります。[...]ただし、QListは、パラメーターの受け渡しと値の戻りのためにQt API全体で使用されます。QListを使用してこれらのAPIとインターフェイスします。(QListドキュメント)
AntonyG

64

世の中変わったんだよ

現在、Qt 5.8にあり、状況が変わったため、ドキュメントが変更されました。それはこの質問に明確で異なる答えを与えます:

QVectorデフォルトの最初の選択肢である必要があります。Tがaまたはusingのいずれかであると宣言されていない限り、常にアイテムをメモリに順番に格納し、ヒープにアイテムを割り当てるため、QVector<T>通常はQList<T>よりもパフォーマンスが向上し ます。QVector<T>QList<T>sizeof(T) <= sizeof(void*)Q_MOVABLE_TYPEQ_PRIMITIVE_TYPEQ_DECLARE_TYPEINFO

QList説明については、使用の長所と短所を参照してください。ただし、QListQt API全体で、パラメーターの受け渡しと値の戻りに使用されます。QListこれらのAPIとのインターフェースに使用します。


2
これは上がるはずで、今は答えとして受け入れられています。
ymoreau 2017年

12

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


3

QtListドキュメントから:

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

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


-2

QVector サイズを変更(増加または減少)できる配列のようなものですが、大量のトランザクションと計算および時間がかかります。

たとえば、アイテムを追加する場合、新しい配列が作成され、すべてのアイテムが新しい配列にコピーされ、新しいアイテムが最後に追加され、古い配列が削除されます。逆に削除することもできます。

ただし、QLinkedListポインタでは機能します。したがって、新しいアイテムが作成されると、新しいメモリスペースだけが割り当てられ、メモリの唯一のチャンクにリンクされます。ポインタで動作するため、より高速で効率的です。

サイズをあまり変更しないQVectorと思われるアイテムのリストがある場合は、おそらく良いでしょうが、通常QLinkedListはほとんどの目的で使用されます。


3
-1:QVectorは事前に割り当てられており、追加とポップのための優れた拡張/縮小戦略を備えているため、あなたが主張するような重いトランザクションは付属していません。プリペンド/挿入には確かにデータ範囲の移動が必要ですが、メモリ内で連続しているため、これは非常に迅速に実行されます(QListのように分散ヒープチャンクとは異なり、キャッシュは連続データでうまく機能します)。QLinkedListがほとんどの目的で使用されているという2番目のステートメントは、明らかに間違っています。ほとんど使用されません。あなたはそれをQListと混同しているかもしれませんか?
DerManu 2015
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.