留個爪,備查
QMultiMap<QString, QString>& remote_map = my_obj->m_MapVersion; // ccc 這里體現了引用的好處,不必整個復制了 qDebug() << "remote_map: " << remote_map.count(); QMultiMap<QString, QString>& remote_fullmap = my_obj->m_MapFullVersion; qDebug() << "m_MapFullVersion: " << remote_fullmap.count();// 遍歷方法一 QMutableMapIterator<QString, QString> i(remote_fullmap); while (i.hasNext()) { if (i.next().key().endsWith("__fixme__")) i.remove(); // fixme qDebug() << "remote1: " << i.key() << ", " << i.value(); } // 遍歷方法二 foreach (const QString &strKey, remote_map.keys()) // values qDebug() << "remote2: " << strKey << ":" << remote_map.value(strKey);
其中foreach是宏替換產生的語法
參考:
http://www.verydemo.com/cj.jsp?c=40&u=qt-rong-qi-lei-jie-shao-he-shi-yong
http://www.devbean.net/2013/01/qt-study-road-2-iterator/
-
Qt 的容器類提供了兩種風格的遍歷器:Java 風格和 STL 風格。這兩種風格的遍歷器在通過非 const 函數對集合進行修改時都是不可用的。
Java 風格的遍歷器
Java 風格的遍歷器是在 Qt4 首先引入的,是 Qt 應用程序首先推薦使用的形式。這種風格比起 STL 風格的遍歷器更方便。方便的代價就是不如后者高效。它們的 API 非常類似於 Java 的遍歷器類,故名。
每一種容器都有兩種 Java 風格的遍歷器:一種提供只讀訪問,一種提供讀寫訪問:
容器 只讀遍歷器 | 讀寫遍歷器 |
---|---|
QList,QQueue | QListIterator QMutableListIterator |
QLinkedList | QLinkedListIterator QMutableLinkedListIterator |
QVector,QStack | QVectorIterator QMutableVectorIterator |
QSet QSetIterator | QMutableSetIterator |
QMap<key, t="">,QMultiMap<key, t=""> | QMapIterator QMutableMapIterator |
QHash<key, t="">,QMultiHash<key, t=""> | QHashIterator QMutableHashIterator |
不同於下面我們將要介紹的 STL 風格的遍歷器,Java 風格的遍歷器指向的是兩個元素之間的位置,而不是指向元素本身。因此,它們可能會指向集合第一個元素之前的位置,也可能指向集合的最后一個元素之后的位置。
我們通過調用hasNext()函數判斷遍歷器之后的位置上有無元素。如果有,調用next()函數將遍歷器跳過其后的元素。next()函數返回剛剛跳過的元素。當然,我們也可以使用hasPrevious()和previous()函數來從尾部開始遍歷,詳細內容可以參考 API 文檔。
QListIterator是只讀遍歷器,不能插入或者刪除數據。如果需要這些操作,我們可以使用QMutableListIterator。
STL 風格的遍歷器
STL 風格的遍歷器從 Qt 2.0 就開始提供。這種遍歷器能夠兼容 Qt 和 STL 的通用算法,並且為速度進行了優化。同 Java 風格遍歷器類似,Qt 也提供了兩種 STL 風格的遍歷器:一種是只讀訪問,一種是讀寫訪問。我們推薦盡可能使用只讀訪問,因為它們要比讀寫訪問的遍歷器快一些。
容器 | 只讀遍歷器 | 讀寫遍歷器 |
---|---|---|
QList,QQueue | QList::const_iterator | QList::iterator |
QLinkedList | QLinkedList::const_iterator | QLinkedList::iterator |
QVector,QStack | QVector::const_iterator | QVector::iterator |
QSet | QSet::const_iterator | QSet::iterator |
QMap<key, t="">,QMultiMap<key, t=""> | QMap<key, t="">::const_iterator | QMap<key, t="">::iterator |
QHash<key, t="">,QMultiHash<key, t=""> | QHash<key, t="">::const_iterator | QHash<key, t="">::iterator |
STL 風格的遍歷器具有類似數組指針的行為。例如,我們可以使用 ++ 運算符讓遍歷器移動到下一個元素,使用 運算符獲取遍歷器所指的元素。對於QVector和QStack,雖然它們是在連續內存區存儲元素,遍歷器類型是`typedef T
,const_iterator類型則是
typedef const T *`。
不同於 Java 風格遍歷器,STL 風格遍歷器直接指向元素本身。容器的begin()函數返回指向該容器第一個元素的遍歷器;end()函數返回指向該容器最后一個元素之后的元素的遍歷器。end()實際是一個非法位置,永遠不可達。這是為跳出循環做的一個虛元素。如果集合是空的,begin()等於end(),我們就不能執行循環。
由於有隱式數據共享(我們會在后面的章節介紹該部分內容),即使一個函數返回集合中元素的值也不會有很大的代價。Qt API 包含了很多以值的形式返回QList或QStringList的函數(例如QSplitter::sizes())。如果你希望使用 STL 風格的遍歷器遍歷這樣的元素,應該使用容器的拷貝,例如:
1
2
3
4
5
6
7
8
9
10
11
|
// 正確的方式
const QList<QString> sizes = splitter->sizes();
QList<QString>::const_iterator i;
for (i = sizes.begin(); i != sizes.end(); ++i)
...
// 錯誤的方式
QList<QString>::const_iterator i;
for (i = splitter->sizes().begin();
i != splitter->sizes().end(); ++i)
...
|
這個問題不存在於那些返回集合的 const 或非 const 引用的函數。隱式數據共享對 STL 風格遍歷器造成的另外影響是,在容器上運行着非 const 遍歷器的時候,不能對容器進行拷貝。Java 風格的遍歷器沒有這個問題。
foreach關鍵字
如果類型名中帶有逗號,比如QPair<int, int="">,我們只能像上面一樣,先創建一個對象,然后使用foreach關鍵字。如果沒有逗號,則可以直接在foreach關鍵字中使用新的對象。
Qt 會在foreach循環時自動拷貝容器。這意味着,如果在遍歷時修改集合,對於正在進行的遍歷是沒有影響的。即使不修改容器,拷貝也是會發生的。但是由於存在隱式數據共享,這種拷貝還是非常迅速的。
因為foreach創建了集合的拷貝,使用集合的非 const 引用也不能實際修改原始集合,所修改的只是這個拷貝。
http://jukezhang.com/2014/11/23/learn-qt-eight/ 《QT學習之路2》摘錄-6(容器)
http://www.devbean.net/2013/01/qt-study-road-2-iterator/