QList和QVector的区别

news/2025/3/16 13:52:47/文章来源:https://www.cnblogs.com/tingtaishou/p/18774852

在Qt中,QList 和 QVector 是两个常用的容器类,用于存储和管理一组元素。它们的功能类似,但在内部实现和性能特性上有一些区别。以下是它们的详细对比:


1. 内部实现

QList

  • 实现方式QList 是一个基于指针数组的容器,存储的是指向实际元素的指针。

  • 内存布局:对于小型对象(如 intQString 等),QList 会直接存储元素;对于大型对象,QList 会存储指向元素的指针。

  • 灵活性QList 的设计使其在插入和删除操作时更加高效。

QVector

  • 实现方式QVector 是一个基于连续内存块的容器,类似于C++标准库中的 std::vector

  • 内存布局QVector 的所有元素都存储在连续的内存块中,访问速度更快。

  • 性能QVector 在随机访问和迭代时性能更好。


2. 性能对比

插入和删除操作

  • QList:在中间插入或删除元素时,QList 的性能通常优于 QVector,因为它只需要移动指针。

  • QVector:在中间插入或删除元素时,QVector 需要移动大量元素,性能较差。

随机访问

  • QList:由于存储的是指针,随机访问时需要解引用,性能稍差。

  • QVector:由于元素存储在连续内存中,随机访问性能更好。

内存占用

  • QList:对于小型对象,QList 的内存占用可能更小;对于大型对象,QList 需要额外的指针存储空间。

  • QVectorQVector 的内存占用更可预测,因为它直接存储元素。


3. 使用场景

适合使用 QList 的场景

  • 需要频繁在中间插入或删除元素。

  • 存储的元素是小型对象(如 intQString 等)。

  • 需要更高的灵活性。

适合使用 QVector 的场景

  • 需要频繁随机访问元素。

  • 存储的元素是大型对象。

  • 需要连续的内存布局(例如与C风格API交互时)。


4. API 兼容性

  • QList 和 QVector 的API非常相似,几乎可以互换使用。

  • 例如,两者都支持以下操作:

    • append():在末尾添加元素。

    • at():访问元素。

    • size():获取元素数量。

    • insert():在指定位置插入元素。

    • removeAt():删除指定位置的元素。


5. 示例代码

QList 示例

cpp
复制
#include <QList>
#include <QDebug>int main()
{QList<int> list;list.append(10);list.append(20);list.append(30);qDebug() << "QList elements:";for (int i = 0; i < list.size(); ++i) {qDebug() << list.at(i);}return 0;
}

QVector 示例

cpp
复制
#include <QVector>
#include <QDebug>int main()
{QVector<int> vector;vector.append(10);vector.append(20);vector.append(30);qDebug() << "QVector elements:";for (int i = 0; i < vector.size(); ++i) {qDebug() << vector.at(i);}return 0;
}

6. Qt 6 中的变化

在 Qt 6 中,QVector 被重新实现为 QList 的别名,这意味着两者在 Qt 6 中是完全相同的类。这样做是为了简化API并减少维护成本。因此,在 Qt 6 中,QList 和 QVector 可以互换使用,没有性能或功能上的区别。


7. 总结

特性QListQVector
内部实现 基于指针数组 基于连续内存块
插入/删除性能 更高效(尤其是中间操作) 较低效(需要移动元素)
随机访问性能 较低(需要解引用) 更高(连续内存访问)
内存占用 小型对象更节省,大型对象需要额外指针 更可预测,直接存储元素
适用场景 频繁插入/删除,小型对象 频繁随机访问,大型对象
Qt 6 中的行为 与 QVector 相同 与 QList 相同
  • 在 Qt 5 及更早版本中,根据具体需求选择 QList 或 QVector

  • 在 Qt 6 中,QList 和 QVector 是相同的类,可以随意使用。

 

 

在Qt中,QList 和 QVector 的遍历速度取决于它们的内部实现和内存布局。以下是它们遍历速度的详细对比:


1. 内存布局对遍历速度的影响

QList

  • 内存布局QList 存储的是指向元素的指针(对于大型对象)或直接存储元素(对于小型对象)。

  • 遍历性能

    • 对于小型对象(如 intQString 等),QList 的遍历速度较快,因为元素直接存储在连续的内存块中。

    • 对于大型对象,QList 的遍历速度较慢,因为需要解引用指针来访问实际数据。

QVector

  • 内存布局QVector 的所有元素都存储在连续的内存块中。

  • 遍历性能QVector 的遍历速度通常比 QList 更快,因为它的内存布局更加紧凑,缓存命中率更高。


2. 遍历方式

使用下标访问(at() 或 []

  • QList 和 QVector 都支持通过下标访问元素。

  • 由于 QVector 的内存布局是连续的,它的下标访问速度通常比 QList 更快。

示例代码

cpp
复制
// QList 遍历
QList<int> list = {1, 2, 3, 4, 5};
for (int i = 0; i < list.size(); ++i) {qDebug() << list.at(i);
}// QVector 遍历
QVector<int> vector = {1, 2, 3, 4, 5};
for (int i = 0; i < vector.size(); ++i) {qDebug() << vector.at(i);
}

使用迭代器

  • 使用迭代器遍历时,QVector 的性能仍然优于 QList,因为连续内存布局减少了缓存未命中的概率。

示例代码

cpp
复制
// QList 迭代器遍历
QList<int> list = {1, 2, 3, 4, 5};
for (auto it = list.begin(); it != list.end(); ++it) {qDebug() << *it;
}// QVector 迭代器遍历
QVector<int> vector = {1, 2, 3, 4, 5};
for (auto it = vector.begin(); it != vector.end(); ++it) {qDebug() << *it;
}

使用范围-based for 循环

  • 范围-based for 循环是C++11引入的语法糖,底层仍然是基于迭代器的。

  • 性能与迭代器遍历类似。

示例代码

cpp
复制
// QList 范围-based for 循环
QList<int> list = {1, 2, 3, 4, 5};
for (int value : list) {qDebug() << value;
}// QVector 范围-based for 循环
QVector<int> vector = {1, 2, 3, 4, 5};
for (int value : vector) {qDebug() << value;
}

3. 性能对比总结

遍历方式QList 性能QVector 性能
下标访问(at() 较慢(需要解引用指针) 更快(连续内存访问)
迭代器遍历 较慢(指针解引用和缓存未命中) 更快(连续内存访问,缓存命中率高)
范围-based for 循环 较慢(基于迭代器) 更快(基于迭代器,连续内存访问)

4. 实际测试

以下是一个简单的性能测试示例,比较 QList 和 QVector 的遍历速度:

cpp
复制
#include <QList>
#include <QVector>
#include <QElapsedTimer>
#include <QDebug>int main()
{const int size = 1000000;QList<int> list;QVector<int> vector;// 填充数据for (int i = 0; i < size; ++i) {list.append(i);vector.append(i);}// 测试 QList 遍历速度QElapsedTimer timer;timer.start();for (int i = 0; i < list.size(); ++i) {volatile int value = list.at(i); // 防止编译器优化}qDebug() << "QList traversal time:" << timer.elapsed() << "ms";// 测试 QVector 遍历速度timer.restart();for (int i = 0; i < vector.size(); ++i) {volatile int value = vector.at(i); // 防止编译器优化}qDebug() << "QVector traversal time:" << timer.elapsed() << "ms";return 0;
}

测试结果

  • 通常情况下,QVector 的遍历速度会比 QList 快 10%-30%,具体取决于元素类型和硬件环境。


5. 总结

  • QVector 的遍历速度更快,因为它使用连续内存布局,缓存命中率更高。

  • QList 的遍历速度较慢,尤其是存储大型对象时,因为需要解引用指针。

  • 如果需要频繁遍历容器,优先选择 QVector

  • 在 Qt 6 中,QList 和 QVector 的实现相同,遍历性能没有区别。

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

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

相关文章

Object obserberd 用法

我是Eric,手机号是13522679763

基于Arduino的自平衡机器人设计

这是一个相对简单,视觉上有效的平衡机器人项目,只需要四个组件来制作。自平衡机器人是一种能使自身保持平衡而不致坠落到地面的装置。它的功能是利用车轮和车身的电机轴线运动来保持平衡。有几种类型的自平衡机器人,在这个特殊的情况下,我将向你展示一种制造两轮平衡机器人…

Scanner进阶学习

Scanner进阶使用hasNextInt(),hasNextFloat(),hasNextDouble()等方法,可用于判断输入数据的类型​ 例:判断输入的数据是否整数类型,或是否是浮点数类型 public static void main(String[] args) {Scanner scanner=new Scanner(System.in);int i=0;float f=0.0f;System…

第三周上课习题

TempConvert.py TempStr = input("请输入带有符号的温度值:") if TempStr[-1] in [F,f]: C = (eval(TempStr[0:-1]) - 32)/1.8 print("转换后的温度是C{:.2f}".format(C)) elif TempStr[-1] in [C, c]: F = 1.8*eval(TempStr[0:-1]) + 32 print("转换…

父子组件传值-@link- 可以互相传递

@Entry@Componentstruct Parent { @State count: number = 1; build() { Column() { Column({ space: 10 }) { //父组件标题 Text(父组件).textStyle() //父组件计数器 Row({ space: 10 }) { Text(@State).textStyle() …

使用 INFINI Gateway 保护 Elasticsearch 集群之修改查询不合理参数(一)

本文将探讨如何使用 INFINI Gateway 修改查询不合理的参数,此方法同样适用于 Opensearch 和 INFINI Easysearch 。 在之前的文章中,我们介绍了如何阻断不合理的查询。有些不合理查询是本身就非常消耗资源,比如模糊查询、嵌套聚合等。还有些不合理查询是因为指定了不合理的参…

20242931 2024-2025-2 《网络攻防实践》第三周作业

20242931 2024-2025-2 《网络攻防实践》第三周作业 1. 实验内容 (1)动手实践tcpdump 使用tcpdump开源软件对在本机上访问www.baidu.com网站过程进行嗅探,回答问题:你在访问www.baidu.com网站首页时,浏览器将访问多少个Web服务器?他们的IP地址都是什么? (2)动手实践Wir…

Android开发--Lesson02--常见的控件

一.简单空间 TextView TextView用来显示文本信息,可以在XML文件中添加并且添加其相对的样式:它的样式主要有以下内容:<TextViewandroid:id="@+id/textViewExample" <!-- 设置TextView的唯一标识符,用于在代码中引用 -->android:layout_width="wra…

AI编程:最疯狂的MCP服务器你一定要试试

我还记得我第一次听说MCP(模型上下文协议)的时候,我心想: “哈?又一个花里胡哨的缩写,这个世界已经快被这些缩写淹没了!” 但当我意识到MCP就像AI界的通用连接器——就像USB-C之于手机和笔记本电脑——我瞬间兴奋了。 再也不用折腾那些只能在某个地方工作的插件或奇怪的…

20241217实验一《Python程序设计》实验报告

20241217 2024-2025-2 《Python程序设计》实验一报告 课程:《Python程序设计》 班级: 2412 姓名: 黄迅 学号:20241217 实验教师:王志强 实验日期:2025年3月12日 必修/选修: 公选课 一、实验内容 1.熟悉Python开发环境; 2.练习Python运行、调试技能;(编写书中的程序…

域自适应

信息时代产生的大量数据使机器学习技术成功地应用在许多领域。大多数机器学习技术需要满足训练集与测试集独立同分布的假设,但在实际应用中这个假设很难满足。 域适应是一种在训练集和测试集不满足独立同分布条件下的机器学习技术。一般情况下的域适应只适用于源域目标域特征空…

JDK8-时间格式化类-时区类-工具类--java进阶day07

1.时间格式化类:DateTimeFormatter1.创建方式 使用DateTimeFormatter调用ofPattern方法即可. 2.格式化方法创建好DateTimeFormatter对象后,调用format方法,将要格式化的日期对象放入即可.3.日期字符串解析 将一个日期字符串变为日期,需要用到日历类对象,调用它的parse方法…