QT中的 容器(container)-大全

一、介绍

Qt库提供了一套通用的基于模板的容器类,可以用这些类存储指定类型的项。比如,你需要一个大小可变的QString的数组,则使用QVector<QString>。

这些容器类比STL(C++标准模板库)容器设计得更轻量、更安全并且更易于使用。如果对STL不熟悉,或者倾向于用“Qt的方式”,那么你可以使用这些类,而不去使用STL的类。(STL容器使用详见首页其他作品)

二、容器类

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函数进行快速的查找,而没有用二叉搜索。

容器也可以嵌套使用,例如QMap<QString,QList<int> >,这里键的类型是QString,而值的类型是QList<int>,需要注意,在后面的“> >”符号之间要有一个 空格,不然编译器会将它当作“>>”操作符对待。

该代码运行环境为Windows,采用Mingw64编译器输出结果。

1. QList容器

QList是一个模板类,提供了一个列表。QList<T>实际上是一个T类型项目的指针数组,所以支持基于索引的访问,而且当项目的数目小于1000时,可以实现在列表中间进行快速的插入操作。

QList提供了很多方便的接口函数来操作列表中的项目,例如插入操作insert()、替换操作replace()、移除操作removeAt()、移动操作move()、交换操作swap()、在表尾添加项目append()、在表头添加项目prepend()、从列表中移除一项并获取这个项目takeAt()及相应的takeFirst()和takeLast()、获取一个项目的索引indexOf()、判断是否含有相应的项目contains()以及获取一个项目出现的次数count()等。

插入

#include "widget.h"#include <QApplication>
#include <QList>
#include <QMap>
#include <QSplitter>
#include <QVector2D>
#include <QVector>
#include <QtAlgorithms>
#include <QtCore>
#include <QtWidgets>void printList(QList<int>&li)
{for(auto it = li.begin();it != li.end();it++){qDebug()<< *it <<"=\t"<< &(*it);}
}int main(int argc, char* argv[])
{QCoreApplication a(argc, argv); //无GUI的窗口QList<int> li;//插入li.insert(li.begin(),1); //在迭代器开始位置插入1li.insert(0,2); //在0序号位置插入 2li.insert(4,100); //在4序号位置插入 100li.append(10); //追加元素10li.push_back(3); // 尾插li.push_front(3); // 头插li.push_back(1);li.push_back(1);li.push_back(1);li.push_back(1);li << 20 << 30<<40;//替换li.replace(0,200);printList(li);return a.exec();
}

运行结果如下,可以看出QList容器的元素地址分配十分规律,一次偏移8字节 ,存储的应该是指针(不确定)

其他操作

QList<int> li;//插入li << 20 << 30<<40<< 50<<60 <<30 ;//删除li.erase(li.begin());li.takeAt(0);//    li.takeLast();   // 删除最后一个元素//    li.takeFirst();  // 删除第一个元素//替换li.replace(3,200); // 3下标 为第四个//统计qDebug()<<"count(3) = "<<li.count(30); //统计元素出现的次数qDebug()<<"contains 50? = "<< li.contains(50);

 QVector容器

插入

插入和QList容器相比,insert方法插入  li.insert(4,100);  报错:不能够超出索引插入元素。

#include "widget.h"#include <QApplication>
#include <QList>
#include <QMap>
#include <QSplitter>
#include <QVector2D>
#include <QVector>
#include <QtAlgorithms>
#include <QtCore>
#include <QtWidgets>void printList(QVector<int>&li)
{for(auto it = li.begin();it != li.end();it++){qDebug()<< *it <<"=\t"<< &(*it);}
}
int main(int argc, char* argv[])
{QCoreApplication a(argc, argv); //无GUI的窗口QVector<int> li;//插入li.insert(li.begin(),1); //在迭代器开始位置插入1li.insert(0,2); //在0序号位置插入 2
//    li.insert(4,100); //在4序号位置插入 100li.append(10); //追加元素10li.push_back(3); // 尾插li.push_front(3); // 头插li.push_back(1);li.push_back(1);li.push_back(1);li.push_back(1);li << 20 << 30<<40;//替换li.replace(0,200);printList(li);return a.exec();
}

运行结果如下,可以看到内存直接分配的间隔为4字节,比QList小 ,存储的为int的大小

 

其他方法

比QList容器多个capacity 方法,类似与std::vector容器

QLinkedList

QLinkedList 的废弃:从 Qt 6.0 开始,QLinkedList 容器已被废弃并从 Qt 容器库中移除。Qt 团队推荐使用 std::list(C++ 标准库中的双向链表)作为替代

QLinkedList(Qt链表)是一个 C++ 标准库中的双向链表容器类,它是 Qt 框架中的一部分。Qt 框架是一个跨平台的应用程序开发框架,广泛应用于 GUI 和非 GUI 程序的开发。QLinkedList 提供了一个高效的数据结构,用于存储和管理元素的集合。

重要性:

动态大小:QLinkedList 的大小是动态的,可以根据需要轻松添加或删除元素。这使得它在处理具有不确定大小的数据集时非常有用。
双向遍历:与 QVector 和 QList 不同,QLinkedList 允许从头到尾以及从尾到头的双向遍历。这种遍历方式在某些场景下会非常有用。
高效的插入和删除操作:在链表的中间插入或删除元素的时间复杂度为 O(1)。这使得 QLinkedList 在需要频繁插入和删除元素的场景中,具有优势。
不需要连续内存:与 QVector 和 QList 相比,QLinkedList 的元素不需要存储在连续的内存空间中。这意味着在内存碎片化的情况下,QLinkedList 可能更容易分配内存。

QLinkedList 的性能优化

QLinkedList 是 Qt 提供的双向链表容器,适用于需要频繁插入和删除元素的场景。在某些情况下,使用 QLinkedList 可以获得更好的性能。以下是关于 QLinkedList 性能优化的一些建议:

适用场景选择:在需要频繁插入和删除元素的场景下,使用 QLinkedList 是合适的,因为它在这些操作上具有优秀的性能。然而,如果需要频繁地随机访问元素,QList 或 QVector 可能是更好的选择,因为它们提供更快的随机访问速度。
使用迭代器:QLinkedList 提供了迭代器接口,以高效地遍历链表。在需要遍历链表时,使用迭代器可以获得更好的性能。要注意的是,在遍历过程中插入或删除元素时,应使用迭代器的 insert() 和 remove() 函数,以保持链表的完整性。
减少内存分配次数:尽管 QLinkedList 在插入和删除元素时性能优越,但它的内存分配次数相对较多。为了提高性能,可以预先估计链表的大小,并通过 reserve() 函数预留相应的内存空间,以减少内存分配次数。
使用空间局部性:QLinkedList 的元素存储在非连续的内存地址中,这可能导致 CPU 缓存利用率降低。在可能的情况下,尝试让相邻的元素在逻辑上也相邻,以提高空间局部性。
避免频繁拷贝:链表的拷贝操作相对较慢。如果需要共享数据,可以考虑使用 QSharedPointer 进行引用计数,以避免频繁的拷贝操作。
总之,为了充分发挥 QLinkedList 的性能优势,开发者应在合适的场景下使用它,并采用迭代器、预留内存等方法进行优化。同时,也要注意避免在不适合的场景下使用 QLinkedList,以确保整体性能的最优化。

插入

容器的insert插入方法不能指定下标,需要迭代器,且没有replace方法。

template <typename T>
void printList(QLinkedList<T>&li)
{for(auto it = li.begin();it != li.end();it++){qDebug()<< *it <<"=\t"<< &(*it);}}int main(int argc, char* argv[])
{QCoreApplication a(argc, argv); //无GUI的窗口QLinkedList<int> li;//插入li.insert(li.begin(),1); //在迭代器开始位置插入1
//       li.insert(0,2); //在0序号位置插入 2
//       li.insert(4,100); //在4序号位置插入 100li.append(10); //追加元素10li.push_back(3); // 尾插li.push_front(3); // 头插li.push_back(1);li.push_back(1);li.push_back(1);li.push_back(1);li << 20 << 30<<40;//替换
//       li.replace(0,200);printList(li);a.exec();
}

结果如下,可以看到元素直接不是顺序存储的,是通过指针链接在一起的,两个相连元素之间大概相差32字节,(因为是双向链表,内存随机分配,每个节点应该包含了 int类型4字节和两个指针16字节,再加上内存偏移)

其他操作

    QLinkedList<int> li;//插入li << 20 << 30<<40<< 50<<60 <<30 ;//删除li.erase(li.begin());
//        li.takeAt(0);//    li.takeLast();   // 删除最后一个元素//    li.takeFirst();  // 删除第一个元素//替换//统计qDebug()<<"count(3) = "<<li.count(30); //统计元素出现的次数qDebug()<<"contains 50? = "<< li.contains(50);//访问元素li.back();li.front();QLinkedList<int>::iterator it = std::find(li.begin(),li.end(),30);if(it!= li.end()){qDebug() <<*it;}

QStack

QStack(Qt Stack)是一个来自于Qt框架的容器类,类似于C++标准库中的std::stack。QStack容器是一种后进先出(LIFO)的数据结构,即最后一个进入堆栈的元素将最先被移除。QStack继承了QVector,所以它拥有QVector的所有功能,同时提供了堆栈的特定操作。
由于QStack继承自QVector,因此它还具有QVector的所有成员函数,如append()、at()、capacity()、contains()、count()、data()、fill()、indexOf()、insert()、lastIndexOf()、mid()、prepend()、remove()、removeAll()、removeAt()、removeFirst()、removeLast()、replace()、reserve()、resize()、size()、squeeze()、startsWith()、swap()、takeAt()、takeFirst()、takeLast()、value()等。然而,在使用QStack时,最好坚持使用堆栈特定的接口,以保持代码的清晰性和可读性。
 

#include "widget.h"#include <QApplication>
#include <QList>
#include <QMap>
#include <QSplitter>
#include <QVector2D>
#include <QVector>
#include <QtAlgorithms>
#include <QtCore>
#include <QtWidgets>template <typename T>
void printList(QStack<T>&li)
{for(auto it = li.begin();it != li.end();it++){qDebug()<< *it <<"=\t"<< &(*it);}}int main(int argc, char* argv[])
{QCoreApplication a(argc, argv); //无GUI的窗口QStack<int>s;s.reserve(100); //提前分配内存s.size(); //获取数据大小s.capacity(); //查看容量大小s.push(2);s.push(3);s.push(4);s.push(5);s.insert(0,1);s.insert(1,4);//查看栈顶元素s.top();//弹出栈顶元素s.pop();printList(s);a.exec();
}

运行结果如下,栈是一种顺序存储的容器,每个元素直接相隔4字节大小。

其他用法

s.toList(); //转为QList容器s.toStdVector(); //转为std::vectorprintList(s);qDebug()<<"stack size = "<<sizeof(s);QList<int>l=s.toList();std::vector<int> v=s.toStdVector();printList(l);qDebug()<<"QStack  size = "<<sizeof(l);qDebug()<<"std::vector  size = "<<sizeof(v);v.push_back(10);qDebug()<<"std::vector  size = "<<sizeof(v);

这里补充下关于QStack容器大小的问题,stack容器里有5个int类型的容器,我们可能以为sizeof的大小的5*4 =20;但是这里却是8字节,转为STL中的容器,可以看到结果如下所示,这些容器的内部会有各自的实现。

QQueue容器

QQueue 是 Qt 库中的一个容器类,它表示一个双端队列(double-ended queue,简称 deque)。QQueue 提供了在队列两端进行高效插入和删除操作的功能。QQueue 继承自 QList,可以在首尾方便地添加和删除元素。下面是一些 QQueue 的使用场景:

任务队列:可以用 QQueue 来管理一个任务队列,将待处理的任务添加到队列中,然后依次处理并移除已完成的任务。这种场景下,可以将 QQueue 当作一个先进先出(FIFO)数据结构来使用。
消息队列:在多线程应用中,可以使用 QQueue 存储线程间通信的消息。主线程将消息添加到队列中,子线程从队列中取出消息并处理。这种场景下,需要确保对队列的访问是线程安全的,可以通过加锁等机制实现。
数据缓冲:在处理大量数据时,可以使用 QQueue 作为缓冲区,存储已经处理过的数据,以便在需要时能够快速访问。例如,在处理实时音频或视频数据时,可以将已处理的数据帧存入 QQueue 中,以备后续的播放或分析使用。
编程算法:QQueue 可以用于实现一些编程算法,如宽度优先搜索(BFS)等。通过将待处理的节点添加到队列中,可以保证算法的执行顺序。
事件处理:在事件驱动的程序中,可以使用 QQueue 存储待处理的事件。当事件发生时,将事件对象添加到队列中,然后逐个处理并删除队列中的事件。

比QVector容器多了enqueue插入元素的方法。

综上所述,QQueue作为一种实用的数据结构,广泛应用于不同领域的软件开发。了解QQueue的重要性和基本概念,将有助于开发者更好地利用这一工具解决实际问题。

QQueue的性能优化


  QQueue 是 Qt 容器类之一,它实现了一个先进先出(FIFO)的队列。QQueue 是 QList 的子类,因此它继承了 QList 的许多特性。为了优化 QQueue 的性能,可以采取以下几个方面的措施:利用 QList 的特性:QQueue 的底层实现基于 QList,所以可以利用 QList 的性能优势。QList 的内存分配策略使得在队列的头部和尾部插入和删除元素具有较高效率。因此,当使用 QQueue 时,尽量避免在队列中间进行插入和删除操作。
预分配内存:如果可以预估队列的最大大小,那么可以使用 QQueue::reserve() 函数预先分配内存。这将有助于减少内存分配和释放的开销,提高性能。
避免频繁的内存分配:在频繁地向队列添加和删除元素时,避免频繁的内存分配和释放。可以考虑使用对象池或其他内存管理技术来重用对象,从而提高性能。
使用 const 成员函数:在遍历队列或访问队列元素时,使用 const 成员函数(如 constFirst() 和 constLast())可以避免不必要的拷贝操作,提高性能。
考虑使用其他容器:在某些特定场景下,QQueue 可能不是性能最优的选择。例如,如果需要处理大量连续内存访问操作,可以考虑使用 QVector。同样,如果需要在列表中间频繁地插入和删除元素,QLinkedList 可能是更好的选择。根据实际需求选择合适的容器类,以实现最佳性能。
总之,在使用 QQueue 时,可以通过充分利用 QList 的特性、预分配内存、避免频繁的内存分配、使用 const 成员函数以及根据需求选择合适的容器类等方法来优化性能。

插入

#include "widget.h"#include <QApplication>
#include <QList>
#include <stack>
#include <queue>
#include <map>
#include <QMap>
#include <QSplitter>
#include <QVector2D>
#include <QVector>
#include <QtAlgorithms>
#include <QtCore>
#include <QtWidgets>
#include <vector>template <typename T>
void printList(QList<T>&li)
{for(auto it = li.begin();it != li.end();it++){qDebug()<< *it <<"=\t"<< &(*it);}}template <typename T>
void printList(QQueue<T>&li)
{for(auto it = li.begin();it != li.end();it++){qDebug()<< *it <<"=\t"<< &(*it);}}int main(int argc, char* argv[])
{QCoreApplication a(argc, argv); //无GUI的窗口QQueue<int>li;li.enqueue(2);li.enqueue(3);li.insert(0,1);li << 20 << 30<<40;//替换li.replace(0,200);qDebug()<<"head = "<<li.head();qDebug()<<"take = "<<li.takeAt(3); //删除元素返回元素值li.dequeue(); //出队列printList(li);a.exec();
}

可以看到 QQueue是一个顺序存储的容器,每个元素之间的间隔为8个字节同QList(继承关系)

​​​​​​​

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/208827.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Xilinx Zynq-7000系列FPGA多路视频处理:图像缩放+视频拼接显示,提供工程源码和技术支持

目录 1、前言免责声明 2、相关方案推荐FPGA图像处理方案FPGA图像缩放方案FPGA视频拼接叠加融合方案推荐 3、设计思路详解HLS 图像缩放介绍Video Mixer介绍 4、vivado工程介绍PL 端 FPGA 逻辑设计PS 端 SDK 软件设计 5、工程移植说明vivado版本不一致处理FPGA型号不一致处理其他…

基于springboot 学生学情预警系统-计算机毕设 附源码57567

springboot 学生学情预警系统 摘 要 科技进步的飞速发展引起人们日常生活的巨大变化&#xff0c;电子信息技术的飞速发展使得电子信息技术的各个领域的应用水平得到普及和应用。信息时代的到来已成为不可阻挡的时尚潮流&#xff0c;人类发展的历史正进入一个新时代。在现实运…

【Java Spring】Spring MVC基础

文章目录 1、Spring MVC 简介2、Spring MVC 功能1.1 Spring MVC 连接功能2.2 Spring MVC 获取参数2.2.1 获取变量2.2.2 获取对象2.2.3 RequestParam重命名后端参数2.2.4 RequestBody 接收Json对象2.2.5 PathVariable从URL中获取参数 1、Spring MVC 简介 Spring Web MVC是构建于…

智慧城市包括哪些内容?有哪些智慧城市物联网方案?

数字城市、智慧城市的发展&#xff0c;离不开对公共基础设施的数字化、智慧化改造升级。通过融合边缘计算、5G、物联网、数字孪生、人工智能等新一代信息技术&#xff0c;助力传统公共基础设施提升增强全流程数据能力、计算能力、服务能力&#xff0c;从而不断丰富公共基础设施…

深度学习记录--logistic回归函数的计算图

计算图用于logistic回归函数 先回顾一下单一样本的logistic回归损失函数的公式&#xff0c;公式如下&#xff1a; 将logistic函数用计算图表示出来(以两个基础量为例)&#xff0c;计算图如下&#xff1a; 前向传播已经完成&#xff0c;接下来完成后向传播 运用链式法则依次求…

[PyTorch][chapter 2][李宏毅深度学习-Regression]

前言&#xff1a; Regression 模型主要用于股票预测,自动驾驶,推荐系统等领域. 这个模型的输出是一个scalar。这里主要以下一个线性模型为基础 它是神经网络的基础模块&#xff0c; 目录&#xff1a; 总体流程 常见问题 Numpy 例子 PyTorch 例子 一 总体流程 1 : 建…

后端Long型数据传到前端js后精度丢失的问题

假设一个场景&#xff0c;MybatisPlus的雪花算法生成long类型主键ID&#xff0c;存入数据库&#xff0c;前端获取到数据后&#xff0c;要执行一个更新操作&#xff08;updateById&#xff09;&#xff0c;但这时会出现无法成功更新的情况&#xff01;这是因为前端在长度大于17位…

【SpringMVC】Spring Web MVC入门(一)

文章目录 前言什么是Spring Web MVC&#xff1f;什么是MVC什么是Spring MVC&#xff1f; Spring Boot 和 Spring MVC 的区别什么是Spring Boot&#xff1f;关系和区别 Spring MVC 学习注解介绍1. SpringBootApplication2. RestController3. RequestMapping3.1 RequestMapping 使…

视频生成的发展史及其原理解析:从Gen2、Emu Video到PixelDance、SVD、Pika 1.0

前言 考虑到文生视频开始爆发&#xff0c;比如11月份就是文生视频最火爆的一个月 11月3日&#xff0c;Runway的Gen-2发布里程碑式更新&#xff0c;支持4K超逼真的清晰度作品(runway是Stable Diffusion最早版本的开发商&#xff0c;Stability AI则开发的SD后续版本)11月16日&a…

Wireshark抓包分析RTMP协议时,出现Unknown问题

进行rtmp推流时&#xff0c;使用wireshark抓包&#xff0c;发现部分包显示Unknown 解决方法&#xff1a; 编辑 -> 首选项 -> Protocols -> RTMPT&#xff0c;这里Maximum packet size默认是32768 将该值调大&#xff0c;比如调成1048576&#xff0c;即可解决该问题。…

【内网安全】搭建网络拓扑,CS内网横向移动实验

文章目录 搭建网络拓扑 ☁环境CS搭建,木马生成上传一句话&#xff0c;获取WebShellCS上线reGeorg搭建代理&#xff0c;访问内网域控IIS提权信息收集横向移动 实验拓扑结构如下&#xff1a; 搭建网络拓扑 ☁ 环境 **攻击者win10地址&#xff1a;**192.168.8.3 dmz win7地址&…

第 374 场 LeetCode 周赛题解

A 找出峰值 枚举 class Solution { public:vector<int> findPeaks(vector<int> &mountain) {int n mountain.size();vector<int> res;for (int i 1; i < n - 1; i)if (mountain[i] > mountain[i - 1] && mountain[i] > mountain[i 1…

人工智能 - 人脸识别:发展历史、技术全解与实战

目录 一、人脸识别技术的发展历程早期探索&#xff1a;20世纪60至80年代技术价值点&#xff1a; 自动化与算法化&#xff1a;20世纪90年代技术价值点&#xff1a; 深度学习的革命&#xff1a;21世纪初至今技术价值点&#xff1a; 二、几何特征方法详解与实战几何特征方法的原理…

阅读笔记|A Survey of Large Language Models

阅读笔记 模型选择&#xff1a;是否一定要选择参数量巨大的模型&#xff1f;如果需要更好的泛化能力&#xff0c;用于处理非单一的任务&#xff0c;例如对话&#xff0c;则可用选更大的模型&#xff1b;而对于单一明确的任务&#xff0c;则不一定越大越好&#xff0c;参数小一…

C++11--右值引用

目录 基本概念 左值和右值 左值引用和右值引用 右值引用使用场景和意义 左值引用使用场景 左值引用的短板 右值引用和移动语义 右值引用引用左值 右值引用的其他使用场景 完美转发 万能引用 完美转发保持值得属性 完美转发使用得场景 基本概念 左值和右值 什么…

前端面试灵魂提问(1)

1.自我介绍 2.在实习中&#xff0c;你负责那一模块 3.any与unknow的异同 相同点&#xff1a;any和unkonwn 可以接受任何值 不同点&#xff1a;any会丢掉类型限制&#xff0c;可以用any 类型的变量随意做任何事情。unknown 变量会强制执行类型检查&#xff0c;所以在使用一个…

Linux线程安全,死锁,生产消费模型,线程池

目录 1.可重入和线程安全 2.死锁 死锁四个必要条件&#xff1a; 避免死锁 3. Linux线程同步 线程同步 生产消费模型的概念理解&#xff08;321原则&#xff09; 生产消费模型都有哪些好处。 串行、并发、并行 条件变量 4.信号量 5.线程池 人的一生为什么要坚持&#xff1…

【ArcGIS Pro微课1000例】0043:深度学习--框架库安装

ArcGIS Pro 中的所有深度学习地理处理工具都要求安装支持的深度学习框架库。 文章目录 深度学习框架库下载深度学习框架库安装注意事项深度学习框架库下载 由于是python开发,可以采用安装包与Pip两种方式安装,本文讲解采用安装包安装。 点击深度学习框架库下载,打开网站,…

大文件分片上传、分片进度以及整体进度、断点续传(一)

大文件分片上传 效果展示 前端 思路 前端的思路&#xff1a;将大文件切分成多个小文件&#xff0c;然后并发给后端。 页面构建 先在页面上写几个组件用来获取文件。 <body><input type"file" id"file" /><button id"uploadButton…

后端项目连接数据库-添加MyBatis依赖并检测是否成功

一.在pom.xml添加Mybatis相关依赖 在Spring Boot项目中&#xff0c;编译时会自动加载项目依赖&#xff0c;然后使用依赖包。 需要在根目录下pom.xml文件中添加Mybatis依赖项 <!-- Mybatis整合Spring Boot的依赖项 --> <dependency><groupId>org.mybatis.s…