1. 程式人生 > >Qt容器類的對象模型及應用(線性結構篇:對於QList來說,sharable默認是false的,但對於接下來講的QVector來說,sharable默認是true)

Qt容器類的對象模型及應用(線性結構篇:對於QList來說,sharable默認是false的,但對於接下來講的QVector來說,sharable默認是true)

連續 ble begin 當我 保存 img article net 內容

用Qt做過項目開發的人,肯定使用過諸如QList、QVector、QLinkList這樣的模板容器類,它們雖然名字長的不同,但使用方法都大致相同, 因為其使用方法都大體相同,很多人可能隨便拿一個容器類來使用,但卻不知道這種選擇是不是最優,這對於對性能要求不苛刻的應用,這種選擇不會有任何影響,但是若性能要求苛刻的應用,無疑直接影響到你的系統的成敗。上述提及的容器類本質上是對數據結構中的線性結構的不同的實現,本文通過介紹各容器類的實現原理,讓我們知道什麽時候該用什麽樣的容器,讓大家不再感到迷茫。

1.QList的對象模型

技術分享圖片

一個QList 的對象模型如上圖,ref表示該對象的引用計數,方便對對象釋放,因為當通過append,insert等向對象添加項時,會通過new的方式從堆中分配內存來保存添加的項,若項數據不超過4個字節(即array中能存儲下項數據),則最多只需new一次,如果有未存放項的array,則不需要new;若項數據超過4字節,因為array中存儲不下超過4個字節的數據,所以至少要new一次,以存放數據項(如上圖中的用戶數據),當array中的所有項都已使用,這時需要再new一次,以增加array的空間大小,註意這裏的array空間是連續的,所以重新分配空間後,需要將原來的空間的內容拷貝到新分配的空間中,並delete到原來的內存空間。上圖中的 alloc表示分配的array的尺寸, array[begin]~array[end],表示使用的array,由此我們可以算出,QList的項個數,size() = end - begin + 1。

sharable表是該對象是否共享,在做對象拷貝的時候需要用到,比如有兩個QList對象,list1 = list2;將list2賦值給list1,如果sharable為true,則僅將list2的對象指針直接賦值給list1的對象指針,這樣的話,當我對list1操作時,實際上是對list2操作,因為兩個對象都指向同一塊內存,若sharable為false,則list1會首先分配一個和list2一樣大小的內存,再把list2的內容拷貝到新分配的內存。

對於QList來說,sharable默認是false的,但對於接下來講的QVector來說,sharable默認是true,所以QVector對象在做拷貝的時候,對象之間會共用同一個對象內存,這個要註意。

2.QVector的對象模型

技術分享圖片

QVector與QList的主要區別是QVector直接把要添加的數據項直接放到數組中,不管數據項有多大,它的空間是都是連續的,若數據項尺寸不超過1個指針長,QList與QVector沒有什麽區別,唯一的區別就是QList采用雙向索引(begin和end),這樣向前添加和向後添加項的時間復雜度是等同的。因為new操作是比較耗時的,使用QVector的resize事先分配若幹空間,這樣在append的時候,就不會再new空間了,也省去了空間拷貝的開銷。

3.QLinkList的對象模型

技術分享圖片

QList、QVector是線性結構中的線性表結構,QLinkList的是線性結構中的鏈表結構,如上圖,QLinkList的對象模型實際上是一個雙向循環鏈表(圖中循環沒有畫出來),紅色色部分是鏈表頭,包含有鏈表的尺寸,是否共享,及引用計數信息。對於每一次append操作,都會new出一個節點(圖黑色部分)。

4.QVarLengthArray對象模型

技術分享圖片

5.由QList、QVector派生的對象

技術分享圖片

https://blog.csdn.net/rabinsong/article/details/9374213

Qt容器類的對象模型及應用(線性結構篇:對於QList來說,sharable默認是false的,但對於接下來講的QVector來說,sharable默認是true)