Qt容器类之一:Qt的容器类介绍
一、介绍
Qt库提供了一套通用的基于模板的容器类,可以用这些类存储指定类型的项。比如,你需要一个大小可变的QString的数组,则使用QVector<QString>。
这些容器类比STL(C++标准模板库)容器设计得更轻量、更安全并且更易于使用。如果对STL不熟悉,或者倾向于用“Qt的方式”,那么你可以使用这些类,而不去使用STL的类。
你可以用两种方式遍历容器内存储的项:Java风格的迭代器和STL风格的迭代器。Java风格的迭代器更易于使用,并且提供了更高级的功能;STL风格的迭代器更高效,并且可以和Qt与STL的泛型算法一起使用。
Qt还提供了foreach关键字使我们方便地遍历容器中的项。
二、容器类
Qt提供了一些顺序容器:QList、QLinkedList、QVector、QStack和QQueue。因为这些容器中的数据都是一个接一个线性存储的,所以称为顺序容器。大多数时候,QList是最好的选择,虽然是用数组实现的,但在它的首尾添加元素都非常快。如果你需要一个链表(linked-list)就用QLinkedList;想要你的项在内存中连续存储,就使用QVector。QStack和QQueue(栈和队列)分别提供了后进先出(LIFO)和先进先出(FIFO)的机制。
Qt还提供了一些关联容器:QMap、QMultiMap、QHash、QMultiHash、QSet。因为这些容器存储的是<键,值>对,比如QMap<Key,T>,所以称为关联容器。其中“Multi”容器支持一个键对应多个值。“Hash”容器在有序集合上使用hash函数进行快速的查找,而没有用二叉搜索。
下表对常用的容器类进行了介绍。
| 类 | 概述 |
|---|---|
| QList<T> | 这是目前使用最频繁的容器类,它存储了指定类型(T)的一串值,可以通过索引来获得。本质上QList是用数组实现的,从而保证基于索引的访问非常快。 |
| QLinkedList<T> | 类似于QList,但它使用迭代器而不是整数索引来获得项。当在一个很大的list中间插入项时,它提供了更好的性能,并且它有更好的迭代器机制。 |
| QVector<T> | 在内存中相邻的位置存储一组值,在开头或中间插入会非常慢,因为它会导致内存中很多项移动一个位置。 |
| QStack<T> | QVector的一个子类,提供后进先出的机制。在当前的QVector中增加了几个方法:push()、pos()、top()。 |
| QQueue<T> | QList的一个子类,提供了先进先出的机制,在当前的QList中增加了几个方法:enqueue()、dequeue()、head()。 |
| QSet<T> | 单值的数学集合,能够快速查找。 |
| QMap<Key, T> | 提供了字典(关联数组)将类型Key的键对应类型T的值。通常一个键对应一个值,QMap以Key的顺序存储数据,如果顺序不重要,QHash是一个更快的选择。 |
| QMultiMap<Key, T> | QMap的子类,提供了多值的接口,一个键对应多个值。 |
| QHash<Key, T> | 和QMap几乎有着相同的接口,但查找起来更快。QHash存储数据没有什么顺序。 |
| QMultiHash<Key, T> | QHash的子类,提供了多值的接口。 |
容器也可以嵌套使用,例如QMap<QString,QList<int> >,这里键的类型是QString,而值的类型是QList<int>,需要注意,在后面的“> >”符号之间要有一个 空格,不然编译器会将它当作“>>”操作符对待。
在各种容器中存储的值类型可以是任何的可赋值的数据类型,像基本的类型double、指针类型、Qt的数据类型(如QString、 QDate、QTime)等。但是QObject以及QObject的子类都不能存储在容器中,不过,可以存储这些类的指针,例如QList<QWidget * >。
三、QList和QMap的示例程序
下面分别对最为常用的QList和QMap进行介绍,而对于其他几个容器,可以参照着进行操作,因为它们的接口函数是很相似的,当然也可以参考帮助手册。
QList的示例程序
新建Qt
5控制台应用,项目名称为
myQList。这里只是为了演示QList容器类的使用,所以没有使用图形界面,这样只需要建立控制台程序就可以了。将main.cpp文件更改如下:
#include <QCoreApplication>
#include <QList>
#include <QDebug>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
//创建QList列表
QList<QString> list;
//插入项目
list << "aa" << "bb";
//在列表尾部添加
list.append("cc");
//在列表头部添加
list.prepend("mm");
//将第一个项目值换为“bc”
list.replace(0, "ss");
//第一次遍历输出列表项目值
qDebug() << "the no.1 list is: ";
for(int i=0; i<list.size(); ++i)
{
qDebug() << list.at(i); //现在列表为ss aa bb cc
}
qDebug() << endl;
//----------------------------------------------------------
QString str = list.takeAt(1); //从列表中删除位置1的项目,并获取它
qDebug() << "at(1) item is: " << str;
//在位置1插入项目
list.insert(1, "ab");
//交换项目1和项目2
list.swap(1,2);
//第二次遍历输出列表项目值
qDebug() << "the no.2 list is: ";
for(int i=0; i<list.size(); ++i)
{
qDebug() << list.at(i); //现在列表为ss bb ab cc
}
qDebug() << endl;
//-----------------------------------------------------------
//查询列表中是否包含“ss”
qDebug() << "contains 'ss' ?" << list.contains("ss");
//查询列表中包含“mm”的个数
qDebug() << "the 'ss' count: " << list.count("ss");
// 第一个“ss”的位置,默认从位置0开始往前查找,返回第一个匹配的项目的位置
qDebug() << "the first 'ss' index: " << list.indexOf("ss");
// 第二个“ss”的位置,我们指定从位置1开始往前查找,未找到则返回-1
qDebug() << "the second 'ss' index: " << list.indexOf("ss", 1);
return a.exec();
}
运行程序,Qt的“应用程序输出”窗口输出如下:
the no.1 list is:
"ss"
"aa"
"bb"
"cc"
at(1) item is: "aa"
the no.2 list is:
"ss"
"bb"
"ab"
"cc"
contains 'ss' ? true
the 'ss' count: 1
the first 'ss' index: 0
the second 'ss' index: -1
QList是一个模板类,提供了一个列表。QList<T>实际上是一个T类型项目的指针数组,所以支持基于索引的访问,而且当项目的数目小于1000时,可以实现在列表中间进行快速的插入操作。
QList提供了很多方便的接口函数来操作列表中的项目,例如插入操作insert()、替换操作replace()、移除操作removeAt()、移动操作move()、交换操作swap()、在表尾添加项目append()、在表头添加项目prepend()、从列表中移除一项并获取这个项目takeAt()及相应的takeFirst()和takeLast()、获取一个项目的索引indexOf()、判断是否含有相应的项目contains()以及获取一个项目出现的次数count()等。
对于QList,可以使用“<<’’操作符来向列表中插入项目,也可以使用“[]”操作符通过索引来访问一个项目,其中项目是从0开始编号的。不过,对于只读的访问,另一种方法是使用at()函数,比操作符要快很多。
QMap的示例程序
新建Qt
5控制台应用,项目名称为
myMap。这里只是为了演示QMap容器类的使用,所以没有使用图形界面,这样只需要建立控制台程序就可以了。将main.cpp文件更改如下:
#include <QCoreApplication>
#include <QMap>
#include <QMultiMap>
#include <QDebug>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
//创建QMap
QMap<QString, int> map;
map["one"] = 1; //向map中插入("one",1)
map["three"] = 3;
//使用insert()函数进行插入
map.insert("seven", 7);
//获取键的值,使用“[ ]”操作符时如果map中没有该键,那么会自动插入
int value1 = map["six"]; //如果map中没有该键,则返回0
qDebug() << "value1:" << value1;
qDebug() << "contains 'six' ?" << map.contains("six") << endl;
//使用value()函数获取键的值,这样当键不存在时不会自动插入
int value2 = map.value("five");
qDebug() << "value2:" << value2;
qDebug() << "contains 'five' ?" << map.contains("five") << endl;
//当键不存在时,value()默认返回0,这里可以设定该值,比如这里设置为9
int value3 = map.value("nine", 9);
qDebug() << "value3:" << value3 << endl;
//map默认是一个键对应一个值,如果重新给该键设置了值,那么以前的会被擦除
map.insert("ten", 10);
map.insert("ten", 100);
qDebug() << "ten: " << map.value("ten") << endl;
//可以使用insertMulti()函数来实现一键多值,然后使用values()函数来获取值的列表
map.insertMulti("two", 2);
map.insertMulti("two", 4);
QList<int> values = map.values("two");
qDebug() << "two: " << values << endl;
//------------------------------------------------------------------
//也可以使用QMultiMap类来实现一键多值
QMultiMap<QString, int> map1, map2, map3;
map1.insert("values", 1);
map1.insert("values", 2);
map2.insert("values", 3);
//可以进行相加,这样map3的“values”键将包含2,1,3三个值
map3 = map2 + map1;
QList<int> myValues = map3.values("values");
qDebug() << "the values are: ";
for (int i=0; i<myValues.size(); ++i)
{
qDebug() << myValues.at(i);
}
return a.exec();
}
运行程序,Qt的“应用程序输出”窗口输出如下:
value1: 0
contains 'six' ? true
value2: 0
contains 'five' ? false
value3: 9
ten: 100
two: (4, 2)
the values are:
2
1
3
QMap类是一个容器类,提供了一个基于跳跃列表的字典(a skip-list-based dictionary)。QMap<Key,T>是Qt的通用容器类之一,它存储(键,值)对并提供了与键相关的值的快速查找。
QMap中提供了很多方便的接口函数,例如插人操作inSert()、获取值value()、是否包含一个键contains()、删除一个键remove()、删除一个键并获取该键对应的值take()、插入一键多值insertMulti()等。
可以使用 “[]”操作符插入一个键值对或者获取一个键的值,不过当使用该操作符获取一个不存在的键的值时,会默认向map中插人该键;为了避免这个情况,可以使用value()函数来获取键的值。当使用value()函数时,如果指定的键不存在,那么默认会返回0,可以在使用该函数时提供参数来更改这个默认返回的值。QMap默认是一个键对应一个值的,但是也可以使用insertMulti()进行一键多值的插入,对于一键多值的情况,更方便的是使用QMap的子类QMultiMap。
参考:
Qt容器类之一:Qt的容器类介绍的更多相关文章
- 【Qt】关于Qt【转】
什么是Qt Qt是一个针对桌面.嵌入式.移动设备的一个跨平台的应用程序开发框架,支持的平台包括Linux.OS X.Windows.VxWorks.QNX.Android.iOS.BlackBerry ...
- Qt环境搭建(Qt Creator)+Visual Studio
1.http://www.cnblogs.com/ranjiewen/p/5318768.html 简述 经常有人问我编写Qt程序时使用什么IDE,其实这个真的很难回答(各有所长),只能说看个人爱好了 ...
- Qt入门学习——Qt 5 帮助文档的使用
Qt入门学习——Qt 5 帮助文档的使用 学习图形界面开发,肯定离不开帮助文档的使用,因为它不像 C 语言那样就那么几个函数接口,图形接口的接口可以用海量来形容,常用的我们可能能记住,其它的真的没有必 ...
- Qt 外观之一 ——Qt Style Sheet
Qt Style Sheet 目录 使用 对于应用程序 创建自定义控件 QSS语法 一般选择器(selector) 伪选择器 解决冲突 使用specificity Namespace冲突 级联效应 设 ...
- Qt 5.7 > Qt Applications
本文翻译自Qt官方文档: http://doc.qt.io/qt-5/qmlapplications.html QML 应用 QML是声明式语言,它使得用户界面以及交互行为可以被"描述&qu ...
- 【学QT】2 - QT/E环境的建立
Arm-Linux嵌入式QT/E环境的建立(qt/e 3.x系列) QT/E 3.x系列比QT/E 2.x系列有非常大的改进,大大提高了开发进度,不再使用tmake,安装也更简单.但 ...
- Qt 绘制图表 - Qt Charts版
一.前言 自从 Qt 发布以来,给广大跨平台界面研发人员带来了无数的福利.但是Qt自己却一直没有提供自带的图表库,这就使得 QWT.QCustomPlot 等第三方图表库有了巨大的生存空间,为了降低开 ...
- 【Qt开发】Qt Creator在Windows上的调试器安装与配置
Qt Creator在Windows上的调试器安装与配置 如果安装Qt时使用的是Visual Studio的预编译版,那么很有可能就会缺少调试器(Debugger),而使用MSVC的Qt对应的原生调试 ...
- Qt Creator提示"Qt没有被正确安装,请运行make install"的解决办法
笔者最近使用Qt在开发一些小程序,觉得这个框架设计确实很好,使用了信号和槽解决了组件之间的通讯问题,可以说是基于C++语言上一个非常大的创新,大大提高了开发人员的编码效率,也使整个C++语言更加抽象. ...
- Qt学习记录--Qt::CaseSensitive
Qt::CaseSensitivity 为枚举类型, 可取值Qt::CaseSensitive 和 Qt::CaseInsensitive, 表示匹配的灵敏度. 比较字符串的时候 Qt::CaseSe ...
随机推荐
- CentOS挂载优盘
插入优盘前: [root@centOS5 mnt]# fdisk -l Disk /dev/hdd: bytes heads, sectors/track, cylinders Units = cyl ...
- C++类使用static小例子(新手学习C++)
//为什么类的成员中不能包括动态分配的数据,若包含静态数据怎么使用?#include <iostream>using namespace std;class point{ priva ...
- [网页游戏开发]进一步了解Morn UI及工作流
Morn UI工作流 Morn Builder不仅仅是对Flash IDE的改进,传统的开发协作是以fla为基础,由于fla是二进制文件,在以svn等版本控制软件协作下,合并过程中会出现各种各样的问题 ...
- LeetCode题解(14)--Longest Common Prefix
https://leetcode.com/problems/longest-common-prefix/ 原题: Write a function to find the longest common ...
- 该项目不在c:\ 请确认该项目的位置
该项目不在c:\ 请确认该项目的位置 - CSDN博客https://blog.csdn.net/feilong1lantern/article/details/50388414 在删除不掉的文件夹目 ...
- Android自定义控件实现带有清除按钮的EditText
首先声明我也是参考了别人的思路,只是稍微做了下修改,增加显示密码与隐藏密码,没有输入字符串时让EditText进行抖动,废话少说这里附上效果图 效果很赞有木有 那么怎么实现这种效果呢?那就跟着我一起来 ...
- nginx网站日志配置
用yum安装的nginx的日志默认安装在路径:/var/log/nginx nginx配置文件:/etc/nginx/nginx.conf (总配置文件)/etc/nginx/conf.d/defau ...
- nyoj 999
nyoj 999: 点击打开题目链接 题目思路,处理一下地图,把 D E 能看到的地方标记一下.然后就是暴力广搜一下.标记状态,因为同样在同一个点,但是你刚出发到达那点和找到D之后到达相同的点和找到E ...
- 嵌入式Linux学习方法——给那些彷徨者(下)
上一章解决了嵌入式Linux的“学什么”问题,这一章则具体来说一下“怎么学”. 只要做好以下3点: 1.学习顺序.学习任何东西都应该由浅入深,不能一口吃下一个大胖子,得循序渐进.很多刚开始想学习Lin ...
- JAVA Synchronized (三) volatile 与 synchronized 的比较
一,volatile关键字的可见性 要想理解volatile关键字,得先了解下JAVA的内存模型,Java内存模型的抽象示意图如下: 从图中可以看出: ①每个线程都有一个自己的本地内存空间--线程栈空 ...