【Qt】为什么QList是数组

为什么QList是数组

结论:在 Qt5 / Qt6 中,QList 不是链表,而是一个披着 list 名字的顺序容器。

一、QList 的历史背景
1. 名字的误导性

QList 这个名字,本身就极具欺骗性。

  • C++ 世界里:list ≈ 链表
  • Qt 世界里:QList ≠ 链表(至少现在不是)

很多认知混乱,并不是程序员不行,而是 API 命名留下的历史债务

2. Qt4 时代的 QList

在 Qt4 时代:

  • QList 对小对象做内嵌存储
  • 对大对象存指针
  • 行为介于数组和链表之间

当时它确实不像 QVector 那么"纯粹",也导致了大量口口相传的"经验结论"。

3. Qt5 / Qt6 的转折

为了性能和可预测性:

  • Qt5 起,QList 内部实现改为连续存储
  • 行为与 QVector 高度一致
  • 但 API 名字和接口被完整保留

于是诞生了今天这个局面:

实现已经变了,但大家的印象没更新。

二、QList 的真实本质
1. 内存模型

在 Qt5 / Qt6 中:

  • 元素存储在连续内存中
  • 支持随机访问 operator[]
  • 迭代器是 RandomAccessIterator

这三点中,只要成立一条,就已经可以否定"链表实现"。

2. 一个简单的自证方法

QList list;

list << 1 << 2 << 3 << 4;

for (int i = 0; i < list.size(); ++i)

{

​ qDebug() << &list[i];

}

如果它是链表,地址不可能连续。

三、QList 的核心特性
1. 随机访问

int v = list[i]; // O(1)

这是 QList 与真正链表在语义上的决定性分水岭

2. 隐式共享(Copy-On-Write)

QList a = b; // O(1)

a[0] = newValue; // 触发 detach

特点:

  • 拷贝"看起来"很便宜
  • 写入时才发生真实拷贝

这是 Qt 框架层面非常重要的设计哲学,但不是免费午餐

3. 插入 / 删除复杂度

list.insert(pos, value);

list.removeAt(pos);

  • 时间复杂度:O(n)
  • 会移动内存
  • 并不比 QVector 更擅长中间插入

因此:

用 QList 解决"频繁中间插入"的问题,是一个误判。

四、QList 的常见误用场景
1. 当成链表使用

QList<Node*> nodes;

// 期望中间插入很快

这是历史经验误导下最常见的错误。

2. 多线程下无锁读写

// 一个线程遍历

for (auto& v : list) {}

// 另一个线程 append

list.append(x);

隐式共享 不等于线程安全

这是 Qt 项目里非常隐蔽、但后果严重的坑。

五、QList vs QVector
1. 行为对比
  • 连续内存:两者都是
  • 随机访问:两者都是
  • 中间插入:两者都是 O(n)
2. 关键差异
  • QVector:语义清晰、无历史歧义
  • QList:API 兼容性强、历史包袱重
3. 工程选择原则

新代码默认 QVector,QList 只为兼容存在。

六、什么时候还可以接受 QList

不是绝对不能用,而是使用场景极少

  • 维护老 Qt 项目
  • 被动接收 Qt API 返回的 QList
  • 项目中已经大量使用 QList,且无性能/并发问题
七、结论
  1. QList 不是链表(Qt5 / Qt6)
  2. 不要用链表思维使用 QList
  3. 隐式共享在多线程下必须显式加锁
  4. QList 不适合并发队列
  5. 新代码优先 QVector
相关推荐
咸鱼2.017 小时前
【java入门到放弃】Dubbo
java·开发语言·dubbo
JAVA面经实录9171 天前
Java企业级工程化·终极完整版背诵手册(无遗漏、全覆盖、面试+落地通用)
java·开发语言·面试
周杰伦fans1 天前
AutoCAD .NET 二次开发:深入理解 EntityJig 的工作原理与正确实现
开发语言·.net
Bat U1 天前
JavaEE|多线程初阶(七)
java·开发语言
谭欣辰1 天前
C++ 排列组合完整指南
开发语言·c++·算法
foundbug9991 天前
自适应滤除直达波干扰的MATLAB实现
开发语言·算法·matlab
XDH_CS1 天前
MySQL 8.0 安装与 MySQL Workbench 使用全流程(超详细教程)
开发语言·数据库·mysql
小短腿的代码世界1 天前
Qt实时盈亏计算深度解析:从持仓数据到动态盈亏展示
开发语言·qt
小康小小涵1 天前
基于ESP32S3实现无人机RID模块底层源码编译
linux·开发语言·python