QT 容器及遍历

QT容器遍历分为Java和STL遍历

STL风格遍历器的语法类似于使用指针对数组的操作。我们可以使用++和--运算符使遍历器移动到下一位置,遍历器的返回值是指向这个元素的指针。例如QVector<T>的iterator返回值是 T *类型,而const_iterator返回值是 const T * 类型(数据为常量,返回值不能修改)。

一个典型的使用STL风格遍历器的代码是:

QList<double>::iterator i = list.begin(); 
while (i != list.end()) { 
       *i = qAbs(*i); 
       ++i; 
}

对于某些返回容器的函数而言,如果需要使用STL风格的遍历器,我们需要建立一个返回值的拷贝,然后再使用遍历器进行遍历。如下面的代码所示:

QList<int> list = splitter->sizes(); 
QList<int>::const_iterator i = list.begin(); 
while (i != list.end()) { 
        doSomething(*i); 
        ++i; 
}

在C++中,很多人都会说,要避免这么写,因为最后一个return语句会进行临时对象的拷贝工作。如果这个对象很大,这个操作会很昂贵。所以,资深的C++高手们都会有一个STL风格的写法:

void sineTable(std::vector<double> &vect)    
{    
                vect.resize(360);    
                for (int i = 0; i < 360; ++i)    
                                vect[i] = std::sin(i / (2 * M_PI));    
} 
// call 
QVector<double> v; 
sineTable(v);

这种写法通过传入一个引用避免了拷贝工作。但是这种写法就不那么自然了。而隐式数据共享的使用让我们能够放心的按照第一种写法书写,而不必担心性能问题。

Qt所有容器类以及其他一些类都使用了隐式数据共享技术,这些类包括QByteArray, QBrush, QFont, QImage, QPixmap和QString。这使得这些类在参数和返回值中使用传值方式相当高效。

不过,为了正确使用隐式数据共享,我们需要建立一个良好的编程习惯。这其中之一就是,对list或者vector使用at()函数而不是[]操作符进行只读访问。原因是[]操作符既可以是左值又可以是右值,这让Qt容器很难判断到底是左值还是右值,而at()函数是不能作为左值的,因此可以进行隐式数据共享。另外一点是,对于begin(),end()以及其他一些非const容器,在数据改变时Qt会进行深复制。为了避免这一点,要尽可能使用const_iterator, constBegin()和constEnd().

最后,Qt提供了一种不使用遍历器进行遍历的方法:foreach循环。这实际上是一个宏,使用代码如下所示:

QLinkedList<Movie> list; 
Movie movie; 
... 
foreach (movie, list) { 
       if (movie.title() == "Citizen Kane") { 
               std::cout << "Found Citizen Kane" << std::endl; 
               break; 
       } 
}

Qt容器类之关联存储容器

Qt提供两种关联容器类型:QMap<K, T>和QHash<K, T>。

QMap<K, T>是一种键-值对的数据结构,它实际上使用跳表skip-list实现,按照K进行升序的方式进行存储。使用QMap<K, T>的insert()函数可以向QMap<K, T>中插入数据,典型的代码如下:

QMap<QString, int> map; 
map.insert("eins", 1); 
map.insert("sieben", 7); 
map.insert("dreiundzwanzig", 23);

同样,QMap<K, T>也重载了[]运算符,你可以按照数组的复制方式进行使用:

map["eins"] = 1; 
map["sieben"] = 7; 
map["dreiundzwanzig"] = 23;
int val = map.value("dreiundzwanzig");

遍历关联存储容器的最简单的办法是使用Java风格的遍历器。因为Java风格的遍历器的next()和previous()函数可以返回一个键-值对,而不仅仅是值,例如:

QMap<QString, int> map; 
... 
int sum = 0; 
QMapIterator<QString, int> i(map); 
while (i.hasNext()) 
       sum += i.next().value();

如果我们并不需要访问键-值对,可以直接忽略next()和previous()函数的返回值,而是调用key()和value()函数即可,如:

QMapIterator<QString, int> i(map); 
while (i.hasNext()) { 
       i.next(); 
       if (i.value() > largestValue) { 
               largestKey = i.key(); 
               largestValue = i.value(); 
       } 
}

Mutable遍历器则可以修改key对应的值:

QMutableMapIterator<QString, int> i(map); 
while (i.hasNext()) { 
       i.next(); 
       if (i.value() < 0.0) 
               i.setValue(-i.value()); 
}

如果是STL风格的遍历器,则可以使用它的key()和value()函数。而对于foreach循环,我们就需要分别对key和value进行循环了:

QMultiMap<QString, int> map; 
... 
foreach (QString key, map.keys()) { 
       foreach (int value, map.values(key)) { 
               doSomething(key, value); 
       } 
} 
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,980评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,178评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,868评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,498评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,492评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,521评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,910评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,569评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,793评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,559评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,639评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,342评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,931评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,904评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,144评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,833评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,350评论 2 342

推荐阅读更多精彩内容