摘要
在Qt庫中為我們提供了一系列的基于模闆的容器類。這些類可以被用來存儲特定類型的項。這些容器類都是隐式共享的,可重入的,并且在速度上進行了優化,記憶體占用少,内聯代碼擴充少,進而可以産生更小的可執行檔案。此外,當他們被用作隻讀容器時,還是線程安全的。
一、常見容器類
在開發一個較高性能需求的應用程式時,程式員會比較關注這些容器類的運
行效率,表2.1列出了QList、QLinkedList和QVector容器 的時間複雜度比較。
容器類 | 查找 | 插入 | 頭部添加 | 尾部添加 |
---|---|---|---|---|
QList | O(1) | O(n) | Amort.O(1) | Amort.O(1) |
QLinkedList | O(n) | O(1) | O(1) | O(1) |
QVector | O(1) | O(n) | O(n) | Amort.O(1) |
二、QList類、 QLinkedList 類和QVector類
1、QList類
QList是迄今為止最常用的容器類,它存儲給定資料類型T的一列數值。
QList不僅提供了可以在清單進行追加的QList::append()和list::prepend()函數,還提供了在清單中間完成插入操作的函數QList:insert()。
QList維護了一個指針數組,該數組存儲的指針指向QList存儲的清單項的内容。
對于不同的資料類型,QList采取不同的存儲政策,存儲政策有以下幾種。
(1)如果T是一個指針類型或指針大小的基本類型(即該基本類型占有的位元組數和指針類型占有的位元組數相同),QList 會将數值直接存儲
在它的數組中。
(2)如果QList存儲對象的指針,則該指針指向實際存儲的對象。
相關例子:
#include <QDebug>
int main(int argc,char *argv[])
{
QList<QString>list;
{
QString str("This is a test string");
list<<str;
}
qDebug()<<list[0]<<"How are you!";
return 0;
}
2. QLinkedList類
QLinkedList是一個鍊式清單,它以非連續的記憶體塊儲存資料。
QLinkedList不能使用下标,隻能使用疊代器通路它的資料項。
3. QVector 類
QVector在相鄰的記憶體中存儲給定資料類型T的一組數值。
QVector既可以使用下标通路資料項,也可以使用疊代器通路資料項。
4. Java風格疊代器周遊容器
Java風格的疊代器是Qt 4新加入的一個功能。
對于每一個容器類,Qt都提供了兩種類型的Java風格疊代器資料類型,即隻讀通路和讀寫通路,其分類見下表。
容器類 | 隻讀疊代器類 | 讀寫疊代器類 |
---|---|---|
QList,QQueue | QListIterator | QMutableListIterator |
QLinkedList | QLinkedListIterator | QMutableLinkedListIterator |
Qvector,QStack | QVectorIterator | QMutableVectorIterator |
5. STL風格疊代器周遊容器
對于每一個容器類,Qt都提供了兩種類型的STL風格疊代器資料類型:一種提供隻讀通路;另- -種提供讀寫通路。
三、QMap類和QHash類
QMap類和QHash類具有非常類似的功能,它們的差别僅在于:
●QHash具有比QMap更快的查找速度;
●QHash以任意的順序存儲資料項,而QMap總是按照鍵Key順序存儲資料;
●QHash的鍵類型Key必須提供operator==()和一個全局的qHash(Key)函數,
而QMap的鍵類型Key必須提供operator<()函數。
二者的時間複雜度比較見下表。
容器類 | 鍵查找 | 插入 |
---|---|---|
平均 | 最壞 | |
QMap | Olog(n) | Olog(n) |
QHash | Amort.O(1) | O(n) |
1. QMap類
QMap<Key,T>提供了一個從類型為Key的鍵到類型為T的值的映射。
2. QHash類
QHash<Key,T>具有與QMap幾乎完全相同的API。QHash維護着一張哈希表(HashTable),哈希表的大小與QHash的資料項的數目相适應。
3. Java風格疊代器周遊容器
對于每一個容器類,Qt都提供了兩種類型的Java風格疊代器資料類型:一種提供隻讀通路;另一種提供讀寫通路。
下面的例子完成了QMap中的插入、周遊和修改。
#include <QDebug>
int main(int argc,char *argv[])
{
QMap<QString,QString>map;
map.insert("beijing","111");
map.insert("shanghai","021");
map.insert("nanjingjing","025");
QMaplterator<QString,QString>i(map);
for(;i.hasNext();)
qDebug()<<" "<<i.key()<<" "<<i.next().value();
QMutableMaplterator<QString,QString>mi(map);
if(mifindNex(111"))
mi.setValue("010");
QMaplterator<QString,QString> modi(map);
qDebug()<<" ";
for(;modi.hasNext();)
qDebug()<<" "<<modi.key()<<" "<<modi.next().value();
return 0;
}
四、QVariant類
1、QVariant類及QVariant與自定義資料類型轉換的方法
這個類型相當于是Java裡面的Object,它把絕大多數Qt提供的資料類型都封裝起來,起到一個資料類型“擦除”的作用。比如我們的 table
單元格可以是string,也可以是int,也可以是一個顔色值,那麼這麼多類型怎麼傳回呢?于是,Qt提供了這個QVariant類型,你可以把這
很多類型都存放進去,到需要使用的時候使用一系列的to函數取出來即可。
比如你把int包裝成一個QVariant,使用的時候要用 QVariant::toInt()重新取出來。這裡需要注意的是,QVariant類型的放入和取出必須是
相對應的,你放入一個int就必須按int取出,不能用toString(), Qt不會幫你自動轉換。資料核心無非就是一個 union,和一個标記類型的
type:傳遞的是整數 123,那麼它union存儲整數123,同時type标志Int;如果傳遞字元串,union存儲字元串的指針,同時type标志
QString。
QVariant 屬于 Qt 的Core子產品,屬于Qt的底層核心之一,ActiveQt、QtScript、QtDeclarative等都嚴重依賴于QVariant。
2、QVariant 可以儲存很多Qt的資料類型
QVariant包括QBrush、QColor、QCursor、QDateTime、QFont、QKeySequence、 QPalette、QPen、QPixmap、QPoint、QRect、
QRegion、QSize和QString,并且還有C++基本類型,如 int、float等。QVariant還能儲存很多集合類型,
如QMap<QSTRING, QVariant>, QStringList和QList。item view classes,資料庫子產品和QSettings都大量使用了QVariant類,,以友善
我們讀寫資料。
3、QVariant也可以進行嵌套存儲,例如:
QMap<QString, QVariant> pearMap;
pearMap["Standard"] = 1.95;
pearMap["Organic"] = 2.25;
QMap<QString, QVariant> fruitMap;
fruitMap["Orange"] = 2.10;
fruitMap["Pineapple"] = 3.85;
fruitMap["Pear"] = pearMap;
QVariant被用于建構Qt Meta-Object,是以是QtCore的一部分。當然,我們也可以在GUI子產品中使用,例如:
QIcon icon("open.png");
QVariant variant = icon;
// other function
QIcon icon = variant.value<QIcon>();
我們使用了value()模版函數,擷取存儲在QVariant中的資料。這種函數在非GUI資料中同樣适用,但是,在非GUI子產品中,我們通常使用
toInt()這樣的一系列函數,如toString()等。