Qt库提供了一组通用的基于模板的容器类( container classes) 。这些容器类可以用来存储指定类型的项目(items),例如,如果需要一个 QString类型的大小可变的数组,那么可以使用QVector< QString> 。在《C十+ Primer》一书中作者就强力推荐使用vector类型和迭代器来取代一般的数组,除非vector无法达到必要的速度要求时才使用数组 。与STL(Standard Template Library,C++的标准模板库)中的容器类相比,Qt中的这些容器类更轻量、更安全,也更容易使用 。如果不熟悉STL或者更喜欢使用Qt way来进行编程,那么就可以使用这些容器类来代替STL的类 。本节内容可以在帮助中参考Container Classes关键字 。
Qt的容器介绍 Qt提供了一些顺序容器:QList,QLinkedList , QVector , QStack 和QQueue 。因为这些容器中的数据都是一个接一个线性存储的,所以称为顺序容器 。对于大多数应用程序而言,使用最多而且最好用的是QList,尽管它是一个数组列表,但是可以快速在其头部和尾部进行添加操作 。如果需要使用一个链表,那么可以使用QLinkedList ;如果希望数据项可以占用连续的内存空间,那么可以使用QVector 。而 QStack 和QQueue分别提供了后进先出(LIFO)和先进先出(FIFO)语义 。
Qt还提供了一些关联容器:QMap, QMultiMap,QHash,QMultiHash和 QSet 。因为这些容器存储的是<键,值>对,比如QMap,所以称为关联容器 。其中,Multi容器用来支持一个键多个值的情况 。表对常用的容器类进行了介绍 。另外,还有QCache和 QContiguousCache,它们提供了对缓存存储中对象的高效散列查找 。
下面对最常用的QList和QMap进行介绍,其他几个容器可以参照这二个进行操作,因为他们的接口函数很相似
新建项目,模板选择Qt控制台应用(Qt Console Application),项目名称为mycontainers 。这里只是为了演示容器类的使用,所以没有使用图形界面,这样只需要建立控制台程序就可以了 。完成后将main.cpp文件更改如下:
#include
QList< T>实际上是一个T类型项目的指针数组,所以它支持基于索引的访问,而且当项目的数目小于1000时,可以实现在列表中间进行快速地插入操作 。
QList,提供了很多方便的接口函数来操作列表中的项目,例如,插入操作insert()、替换操作replace(),移除操作removeAt(),移动操作move()、交换操作swap() ,在表尾添加项目append()、在表头添加项目 prepend(),移除第一个项目removeFirst(),移除最后一个项目removeLast(),从列表中移除一项并获取这个项目takeAt()及相应的takeFirst()和 takeLast(),获取一个项目的索引in-dexOf(),判断是否含有相应的项目contains()以及获取一个项目出现的次数count()等 。
QList可以使用“<<”操作符向列表中插入项目,也可以使用“[]”操作符通过索引来访问一个项目,其中项目是从0开始编号的 。不过,对于只读的访问,另一种方法是使用at()函数,它比“[]”操作符要快很多 。
程序中使用了一些常用的函数,读者不用一下子把整个程序都写出来再运行,而是写一部分就运行一次并查看结果 。
QMap类是一个容器类,它提供了一个基于跳跃列表的字典(a skip-list-based dic-tionary) 。QMap是Qt的通用容器类之一,它存储(键,值)对并提供了与键相关的值的快速查找 。QMap中提供了很多方便的接口函数,例如,插入操作insert(),获取值 value() ,是否包含一个键contains()、删除一个键remove()、删除一个键并获取该键对应的值take(),清空操作 clear()、插入一键多值insertMulti()等 。可以使用“[]”操作符插入一个键值对或者获取一个键的值,不过当使用该操作符获取一个不存在的键的值时,会默认向map中插入该键;为了避免这个情况,可以使用value()函数来获取键的值 。当使用value()函数时,如果指定的键不存在,那么默认会返回0,可以在使用该函数时提供参数来更改这个默认返回的值 。
QMap默认是一个键对应一个值的,但是也可以使用insertMulti()进行一键多值的插入;对于一键多值的情况,更方便的是使用QMap的子类QMultiMap 。
容器也可以嵌套使用,如QMap,这里键的类型是QString,而值的类型是QList< int> 。注意,后面的“>>”符号之间要有一个空格,不然编译器会将它当作“>>”操作符对待 。各种容器存储的值的类型可以是任何的可赋值的数据类型,该类型需要有一个默认的构造函数、一个复制构造函数和一个赋值操作运算符,像基本的类型(如 int和 double)、指针类型、Qt的数据类型(如 QString 和QDate等),但不包括QObject以及QObject的子类(QWidget、QDialog、QTimer等),不过可以存储这些类的指针,如QList
遍历容器 遍历一个容器可以使用迭代器(iterators)来完成,迭代器提供了一个统一的方法来访问容器中的项目 。Qt的容器类提供了两种类型的迭代器:Java风格迭代器和STL风格迭代器 。如果只是想按顺序遍历一个容器中的项目,那么还可以使用Qt的foreach关键字 。
Java风格迭代器 Java风格迭代器从Qt 4时被引入,使用上比STL风格迭代器要方便很多,但是在性能上稍微弱于后者 。每一个容器类都有两个Java风格迭代器数据类型:一个提供只读访问,一个提供读/写访问,如表所列 。
下面将以QList和QMap为例来进行讲解,而QLinkedList、QVector和QSet与QList的迭代器拥有极其相似的接口;类似的,QHash与QMap的迭代器拥有相同的接口 。
新建Qt控制台应用,项目名称为myiterators 。然后将main. cpp文件更改如下:
#include 这里先创建了一个QList列表list, 然后使用list作为参数创建了列表的只读迭代器 。这时,迭代器指向列表的第一个项目的前面(这里是指向项目“A"的前面) 。然后使用hasNext()函数来检查该迭代器后面是否还有项目,如果还有项目,那么使用next()来跳过这个项目,next()函数会返回它所跳过的项目 。当正向遍历结束后,迭代器会指向列表最后一个项目的后面,这时可以使用hasPrevious( )和previous()来进行反向遍历 。
可以看到,Java风格迭代器是指向项目之间的,而不是直接指向项目 。所以,迭代器或者指向容器的最前面,或者指向两个项目之间,或者指向容器的最后面 。
QListIterator没有提供向列表中插入或者删除项目的函数,要完成这些功能,就必须使QMutableListlterator 。这个类增加了insert()函数来完成插入操作,remove( )
函数完成删除操作,setValue()函数完成设置值操作 。在前面程序中的“returna.exec();"前添加如下代码:
QMutableListIterator 可以使用remove()函数来删除上一-次跳过的项目,使用insert()函数在迭代器指向的位置插入一个项目,这时迭代器会位于添加的项目之后,比如这里添加“Q”后,迭代器指向“Q”和“A”之间 。使用QMutableListIterator类的next() 和previous()等函数时会返回列表中项目的一个非const引用,所以可以直接对其赋值;当然也可以使用setValue()函数进行赋值,这个函数是对上一-次跳过的项目进行赋值的 。除了这里讲到的这些函数外,还有findNext( )和findPrevious()函数可以用来实现项目的查找 。
现在可以运行程序,运行结果已经在上面的程序中注释出来了 。
与QListIlterator 类似, QMapIterator提供了toFront( ). toBack( ). hasNext( )、next()、peekNext( )、hasPrevious( )、previous( )和peekPrevious()等函数 。可以在next()、peekNext()、previous( )和peekPrevious()等函数返回的对象上分别使用key()和value()函数来获取键和值 。
还是那样项目,main.cpp
#include 其中,QMap中存储了一些(首都,国家)键值对,然后删除了包含以“City”字符串结尾的键的项目 。对于QMap的遍历,可以先使用next()函数,然后再使用key()和value()来获取键和值的信息 。因为这里很多函数与前面例子中的用法相似,这里就不再过多讲解 。现在运行一下程序,从遍历结果可以看到,QMap是按照键的顺序来存储数据的,比如这里是按照键的字母顺序排列的 。
STL风格迭代器 STL风格迭代器兼容Qt和STL的通用算法(generic algorithms),而且在速度上.进行了优化 。每-一个容器类都有两个STL风格迭代器类型:一个提供了只读访问,另一个提供了读/写访问,如表所列 。因为只读迭代器比读/写迭代器要快很多,所以应尽可能使用只读迭代器 。
下面仍然以QList和QMap为例进行相关内容的讲解 。新建Qt控制台应用,项目名称为myiterators3 。然后将main. cpp文件更改如下:
#include STL风格迭代器的API模仿了数组的指针,例如,使用“十十”操作符来向后移动迭代器使其指向下一个项目、使用“
- 春季老年人吃什么养肝?土豆、米饭换着吃
- 三八妇女节节日祝福分享 三八妇女节节日语录
- 老人谨慎!选好你的“第三只脚”
- 校方进行了深刻的反思 青岛一大学生坠亡校方整改校规
- 脸皮厚的人长寿!有这特征的老人最长寿
- 长寿秘诀:记住这10大妙招 100%增寿
- 春季老年人心血管病高发 3条保命要诀
- 眼睛花不花要看四十八 老年人怎样延缓老花眼
- 香槟然能防治老年痴呆症? 一天三杯它人到90不痴呆
- 老人手抖的原因 为什么老人手会抖
