【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() << &listi;

}

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

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

int v = listi; // O(1)

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

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

QList a = b; // O(1)

a0 = 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
相关推荐
用户805533698039 小时前
不止三件套:QObject 属性系统全关键字与运行时反射!
c++·qt
xcyxiner10 小时前
DicomViewer (vcpkg Windows和ubuntu编译)7
qt
Quz5 天前
QML Hello World 入门示例
qt
xcyxiner8 天前
DicomViewer (dcmtk读取dcm文件)5
qt
xcyxiner9 天前
DicomViewer (后台线程处理文件)4
qt
xcyxiner9 天前
DicomViewer (添加模型类)3
qt
xcyxiner10 天前
DicomViewer (目录调整) 2
qt
xcyxiner10 天前
dcmtk vtk vtk-dicom(gdcm) 编译(debug) v2
qt
LDR00612 天前
Type-C 快充全面升级!LDR6601 赋能个人护理便携电机,重塑剃须刀 / 理发器新体验
c语言·开发语言
雪碧聊技术12 天前
Tree.js是什么?一文讲透
开发语言·javascript·ecmascript