【CAPL语言】UDS DTC老化测试复位脚本
2026/7/9 18:11:07
QList在Qt 6中与QVector完全等价,底层是连续内存动态数组,元素紧挨着存放在一块连续的内存中。QLinkedList底层是双向链表,每个节点独立分配在堆上,通过前驱/后继指针串联。
| 操作 | QList | QLinkedList |
|---|---|---|
按索引访问list[i] | O(1) | 不支持 |
尾部追加append() | O(1) 均摊 | O(1) |
头部插入prepend() | O(n) | O(1) |
| 中间插入(已知位置) | O(n)(需移动后续元素) | O(1)(只改指针) |
| 删除(已知位置) | O(n)(需移动后续元素) | O(1)(只改指针) |
| 查找(按值) | O(n) | O(n) |
| 遍历 | 快(内存连续,缓存命中率高) | 慢(指针跳转,缓存不友好) |
| 内存占用 | 小(仅数据本身) | 大(每个节点额外2个指针) |
#include<QList>QList<int>list1;// 空列表QList<int>list2={10,20,30};// 初始化列表(C++11)QList<int>list3(5);// 5个元素,默认值0QList<QString>list4(5,"hello");// 5个元素,全部为"hello"QList<int>list5=list2;// 拷贝构造(隐式共享,O(1))QList<int>list;list.append(10);// 末尾添加 → [10]list.append(20);// 末尾添加 → [10, 20]list.prepend(5);// 头部添加 → [5, 10, 20]list.insert(1,8);// 在索引1处插入 → [5, 8, 10, 20]list<<30<<40;// 流式插入 → [5, 8, 10, 20, 30, 40]list.push_back(50);// 等同于 append → [5, 8, 10, 20, 30, 40, 50]list.push_front(1);// 等同于 prepend → [1, 5, 8, 10, 20, 30, 40, 50]QList<int>list={10,20,30,40,50};list[0];// 10(可读可写)list[0]=99;// 修改第一个元素list.at(1);// 20(只读,比 [] 更快,不触发深拷贝)list.first();// 99(第一个元素,可读可写)list.last();// 50(最后一个元素,可读可写)list.constFirst();// 99(只读版本)list.constLast();// 50(只读版本)list.value(10);// 索引越界时返回默认值0(不崩溃!)list.value(10,-1);// 索引越界时返回-1list.data();// 返回指向第一个元素的指针(可传给C函数)QList<int>list={10,20,30,40,50};list.removeAt(2);// 删除索引2 → [10, 20, 40, 50]list.removeFirst();// 删除第一个 → [20, 40, 50]list.removeLast();// 删除最后一个 → [20, 40]list.removeOne(20);// 删除第一个值为20的 → [40]list.removeAll(40);// 删除所有值为40的 → []list.clear();// 清空所有元素// take 系列:删除并返回被删元素intval1=list.takeAt(1);// 删除索引1并返回它intval2=list.takeFirst();// 删除第一个并返回它intval3=list.takeLast();// 删除最后一个并返回它// erase:通过迭代器删除autoit=list.begin()+1;list.erase(it);// 删除迭代器指向的元素list.erase(list.begin(),list.begin()+2);// 删除一个范围QList<int>list={10,20,30,20,40};list.indexOf(20);// 1(首次出现的索引)list.lastIndexOf(20);// 3(最后出现的索引)list.contains(30);// truelist.count(20);// 2(出现次数)list.replace(2,99);// 将索引2替换为99 → [10, 20, 99, 20, 40]QList<int>list={10,20,30,40,50};QList<int>sub=list.mid(1,3);// 从索引1取3个 → [20, 30, 40]QList<int>sub2=list.mid(2);// 从索引2取到末尾 → [30, 40, 50]QList<int>a={1,2};QList<int>b={3,4};QList<int>c=a+b;// 合并 → [1, 2, 3, 4]a+=b;// a 变为 [1, 2, 3, 4]list.size();// 元素个数list.count();// 等同于 size()list.isEmpty();// 是否为空list.empty();// 等同于 isEmpty()(STL兼容)#include<QLinkedList>QLinkedList<int>list1;// 空链表QLinkedList<int>list2={10,20,30};// 初始化列表(C++11)QLinkedList<int>list3=list2;// 拷贝构造(隐式共享,O(1))QLinkedList<int>list;list.append(10);// 尾部添加 → [10]list.append(20);// 尾部添加 → [10, 20]list.prepend(5);// 头部添加 → [5, 10, 20](O(1),比QList快!)list<<30<<40;// 流式插入 → [5, 10, 20, 30, 40]list.push_back(50);// 等同于 appendlist.push_front(1);// 等同于 prependQLinkedList<int>list={10,20,30,40,50};list[0];// 编译报错!QLinkedList不支持索引访问list.at(1);// 编译报错!list.indexOf(20);// 没有这个方法!list.mid(1,3);// 没有这个方法!// 只能这样访问:list.first();// 10(第一个元素)list.last();// 50(最后一个元素)list.front();// 10(STL兼容,等同于first)list.back();// 50(STL兼容,等同于last)list.startsWith(10);// truelist.endsWith(50);// trueQLinkedList<int>list={10,20,30,40,50};list.removeFirst();// 删除第一个 → [20, 30, 40, 50]list.removeLast();// 删除最后一个 → [20, 30, 40]list.removeOne(30);// 删除第一个值为30的 → [20, 40]list.removeAll(20);// 删除所有值为20的 → [40]list.clear();// 清空// take 系列:删除并返回intval1=list.takeFirst();// 删除第一个并返回intval2=list.takeLast();// 删除最后一个并返回// erase:通过迭代器删除(O(1)!)autoit=list.begin();++it;list.erase(it);// 删除迭代器指向的元素,O(1)QLinkedList<int>list={10,20,30,20,40};list.contains(20);// true(需要遍历,O(n))list.count(20);// 2(需要遍历,O(n))// QLinkedList → std::listQLinkedList<double>qlist={1.2,0.5,3.14};std::list<double>stdlist=qlist.toStdList();// std::list → QLinkedListstd::list<double>stdlist2={1.1,2.2,3.3};QLinkedList<double>qlist2=QLinkedList<double>::fromStdList(stdlist2);QList<int>list={10,20,30,40,50};// ===== STL 风格(推荐) =====// 只读迭代器for(autoit=list.constBegin();it!=list.constEnd();++it)qDebug()<<*it;// 读写迭代器for(autoit=list.begin();it!=list.end();++it){*it=*it*2;// 可以修改元素}// C++11 范围 for(最简洁)for(intval:list)qDebug()<<val;// ===== Java 风格 =====// 只读QListIterator<int>it(list);while(it.hasNext())qDebug()<<it.next();// 读写QMutableListIterator<int>mit(list);while(mit.hasNext()){intval=mit.next();if(val==30)mit.remove();// 删除当前元素}QLinkedList<int>list={10,20,30,40,50};// ===== STL 风格 =====// 只读迭代器for(autoit=list.constBegin();it!=list.constEnd();++it)qDebug()<<*it;// 读写迭代器for(autoit=list.begin();it!=list.end();++it)*it=*it*2;// C++11 范围 forfor(intval:list)qDebug()<<val;// ===== 迭代器插入/删除(QLinkedList 的核心优势) =====autoit=list.begin();++it;// 指向第二个元素list.insert(it,15);// 在20前面插入15,O(1)!list.erase(it);// 删除20,O(1)!// ===== Java 风格 =====QLinkedListIterator<int>it2(list);while(it2.hasNext())qDebug()<<it2.next();QMutableLinkedListIterator<int>mit(list);while(mit.hasNext()){intval=mit.next();if(val==30)mit.remove();}两者都支持隐式共享,赋值和传参时不会立即复制数据,只有在修改时才真正复制。
QList<int>list1={10,20,30};QList<int>list2=list1;// O(1)!不复制数据,共享同一内存list2[0]=99;// 此时才触发深拷贝(写时复制)// list1: [10, 20, 30] ← 不受影响// list2: [99, 20, 30]| QList | QLinkedList | |
|---|---|---|
| 使用频率 | 95% 的场景 | 5% 的场景 |
| 默认选择 | 是 | 否 |
| 适用场景 | 通用,几乎万能 | 频繁头/中间插入删除 + 不需要索引访问 |
| Qt官方建议 | 优先使用 | 仅在性能测试证明更快时才用 |
实践原则:先用QList写代码,如果性能测试发现瓶颈在插入/删除操作上,再考虑换成QLinkedList。不要过早优化。
end~