2011-07-06 70 views
59

我有一個整數列表,我需要迭代,但數組不足。 向量和列表之間有什麼區別,在我選擇類型之前有什麼我需要知道的?QVector vs QList

只是要清楚,我讀過的QT文檔但這是我所知道的範圍內:

的QList,QLinkedList和QVector提供類似的功能。這裏有一個概述:

  • 對於大多數目的,QList是正確的類使用。它的基於索引的API比QLinkedList的基於迭代器的API更方便,並且由於它將項目存儲在內存中的方式通常比QVector更快。它也擴展到可執行文件中的較少代碼。
  • 如果您需要一個真正的鏈接列表,並保證在列表中間有恆定時間插入,並且迭代器能夠使用項目而不是索引,請使用QLinkedList。
  • 如果您希望項目佔用相鄰的內存位置,請使用QVector。

回答

100

QVector大致類似於std::vector,正如您可能從名字中猜出的那樣。 QList更接近boost::ptr_deque,儘管與std::list有明顯關聯。它不直接存儲對象,而是存儲指向它們的指針。您可以獲得兩端快速插入的所有好處,並且重新分配涉及洗牌指針而不是複製構造函數,但會丟失實際的std::dequestd::vector的空間局部性,並獲得大量堆分配。它確實做出了一些決定,以避免小對象的堆分配,重新獲得空間局部性,但根據我的理解,它僅適用於小於int的事物。

QLinkedList類似於std::list,並且具有它的所有缺點。一般來說,這應該是你最後一個容器的選擇。

QT庫非常喜歡使用QList對象,所以在自己的代碼中使用它們有時可以避免一些不必要的乏味。額外的堆使用和實際數據的隨機定位理論上可能會在某些情況下受到傷害,但通常是不可忽略的。所以我會建議使用QList,直到分析建議更改爲QVector。如果您希望連續分配很重要[請閱讀:您正在與期望T[]而不是QList<T>]的代碼進行交互,這也可能是從QVector開始的理由。


如果您一般詢問容器,只是使用QT文檔作爲參考,那麼上述信息就沒那麼有用了。

std::vector是一個可以調整大小的數組。所有元素都相鄰存儲,您可以快速訪問各個元素。缺點是插入僅在一端有效。如果你把東西放在中間或開始,你必須複製其他物體以騰出空間。在大的表示法中,最後的插入是O(1),插入的其他地方是O(N),隨機訪問是O(1)。

std::deque是類似的,但不保證對象存儲在彼此相鄰,並允許在兩端插入爲O(1)。它還需要一次分配更小的內存塊,這有時很重要。隨機訪問爲O(1),中間插入爲O(N),與vector相同。空間局部性比std::vector差,但對象往往是聚集在一起,所以你可以獲得一些好處。

一個std::list是一個鏈表。它需要三個標準順序容器的最大內存開銷,但可以在任何地方提供快速插入...提前知道需要插入的位置。它不提供對單個元素的隨機訪問,所以你必須迭代O(N)。但是一旦出現,實際的插入就是O(1)。 std::list的最大好處是可以快速將它們拼接在一起......如果將整個範圍的值移動到不同的std::list,則整個操作爲O(1)。將列表中的引用無效也很難,這有時很重要。

作爲一般規則,我寧願std::dequestd::vector,除非我需要能夠將數據傳遞給需要原始陣列庫。 std::vector保證連續,所以&v[0]適用於此目的。我不記得我最後一次使用std::list,但幾乎可以肯定,因爲我需要更強大的保證參考文件有效。

+1

真棒,非常感謝詳細的回覆 – jcuenod

+0

FWIW,std :: deque對引用有很好的保證。迭代器很容易失效,但指向成員的指針對於出隊操作非常健壯。 – Ben

+0

很好的回答。但我還有一個問題:迭代速度更快?我有一組對象,它們並不經常插入或移除,但我需要儘可能快地遍歷對象。哪個更快? – gromit190

10

QVector類似於std::vectorQLinkedListstd::list類似。 QList是一個基於索引的向量,但內存位置不保證(如std::deque)。

-1

QVector就像一個可以改變大小(增加或減少)的數組,但它帶有繁重的事務和計算以及時間。

例如,如果要添加項目,則會創建一個新陣列,將所有項目複製到新陣列,將新項目添加到末尾,並刪除舊陣列。反之亦然刪除。

但是,QLinkedList與指針一起工作。因此,當創建一個新項目時,只需分配一個新的內存空間並鏈接到唯一的內存塊。由於它可以與指針一起工作,所以它更快更高效。

如果您有不期望改變大小的項目列表,QVector可能不錯,但通常QLinkedList用於大多數目的。

+2

-1:QVector沒有大量交易正如你聲稱的那樣,因爲它預先分配並且有一個好的增長/縮小策略來追加和彈出。上傳/插入實際上需要移動數據範圍,但由於它們在內存中連續存在,因此可以非常快速地完成(與使用QList的分散堆塊不同,高速緩存可以很好地處理連續數據)。 你的第二個說法是,QLinkedList用於大多數目的顯然是錯誤的。這是最罕用的。你可能會混淆QList? – DerManu

4

從QtList DOC:

  • 的QList在大多數情況下使用。對於具有上千個項目的結構,可以在中間高效插入,並提供索引訪問。 prepend()append()非常快,因爲內存在內部陣列的兩端預先分配。 QList<T>是類型T的指針的陣列。如果T具有指針或Qt的共享狀指針類型,對象被直接存儲在陣列

  • QVector在很多append()或新項目insert()的情況下,可以優選的其大小大於指針,因爲QVector會爲單個堆分配中的項分配內存。對於QList,插入新項目的追加需要在堆上分配新項目的內存。簡而言之,如果您希望項目佔用相鄰的內存位置,或者您的項目大於指針,並且希望避免在插入時分別在堆上分配它們的開銷,請使用QVector

12

事情已經改變,

我們現在的Qt 5.8,情況發生了改變,因此文檔。它給出了這個問題的一個明確和不同的答案:

QVector應該是你的默認第一選擇。 QVector通常會比QList提供更好的性能,因爲QVector始終會將其項目順序存儲在內存中,除非sizeof(T)< = sizeof(void *)並且T已經聲明爲 ,否則QList將在堆上分配其項目 是無論是Q_MOVABLE_TYPE或使用 Q_DECLARE_TYPEINFO一個Q_PRIMITIVE_TYPE。

請參閱使用的QList爲 解釋的優點和缺點。然而,QList作在整個的Qt API用於傳遞 參數和返回值。使用QList與那些 API接口。

+1

這應該上去了,現在被接受爲答案。 – ymoreau