QVector
1. QVector 是什么?
QVector 是 Qt 框架提供的一个模板类,它是一个动态数组。你可以把它理解为 C++ 标准库中的 std::vector 的 Qt 版本。
核心特点:
-
动态大小: 它可以在运行时动态地增加或减少其容量,你不需要在编译时指定固定的大小。
-
连续存储: 它的元素在内存中是连续存储的。这意味着通过索引访问元素(例如
vector[5])的速度非常快,因为可以直接通过地址偏移来计算位置。 -
Qt 风格: 它提供了完整的 Qt 风格的 API,能与 Qt 的其他部分(如信号槽、foreach 宏、迭代器等)无缝集成。
2. 基本用法
2.1 包含头文件和创建对象
包含头文件
#include <QVector>
创建对象
//创建一个空的QVecotr,用于存储int类型的数据 QVector<int> vec; //创建一个厨师大小为10的QVector,每个元素默认初始化为0 QVector<int> vec2(10); //创建一个初始大小为5的QVector,每个元素都初始化为42 QVector<int> vec3(5, 42); //使用初始化列表(C++11及以上) QVector<int> vec4 = { 1,2,3,4,5 };
2.2 添加元素
QVector<QString> fruits; //1.append() 或push_back() 在末尾添加元素 fruits.append("Apple"); fruits.push_back("Banana");//与append()效果相同 //2.prepend()或者push_front();//在开头添加元素 fruits.prepend("Orange"); //3.insert(); 在指定位置插入元素 fruits.insert(1, "Grape");//在索引1的位置,就是第二个插入"Grape" // 此时 fruits 的内容: ["Orange", "Grape", "Apple", "Banana"]
2.3 访问元素
重要: 确保索引在有效范围内 [0, size()-1],否则会导致未定义行为。
QVector<QString> fruits = { "Apple","Banana","Orange" };
//1.使用operator[] (不检查边界,速度更快)
QString first = fruits[0];//"Apple"
//2.使用at() (不检查边界)
QString second = fruits.at(1);//结果:"Banana"
//QString second1 = fruits.at(100);//会报异常
//3.访问第一个和最后一个
QString front = fruits.first();//结果:"Apple"
QString back = fruits.last();//结果:"Orange"
//4.修改元素
fruits[0] = "Mango";// 现在第一个元素变成了 "Mango"
2.4 删除元素
QVector<int> numbers = { 10,20,30,40,50,30 }; //1. removeAt() 删除指定位置的元素 numbers.removeAt(2);//删除索引为2的元素(30) // 现在 numbers: [10, 20, 40, 50, 30] //2.removeOne()删除第一个匹配到的值 numbers.removeOne(30); // 现在 numbers: [10, 20, 40, 50] numbers.removeOne(25); //3.removeAll() 删除所有匹配的值 numbers = { 10,20,30,40,50,30 }; numbers.removeAll(30);//删除所有的30 // 现在 numbers: [10, 20, 40, 50] // 4. removeFirst() / removeLast() / pop_front() / pop_back(): 删除首/尾元素 numbers.removeFirst(); // 删除 10 numbers.pop_back(); // 删除 50 // 5. clear(): 清空整个 QVector numbers.clear();
2.5 获得QVecotr 数量
//获得QVecotr 数量 QVector<int> numbers = { 10,20,30,40,50,30 }; int size = numbers.size();
int size = vec.count();
2.6 查找和判断
QVector<QString> vec = { "A","B","C","D" };
//1.contains() 判断是否包含某个元素
bool hasB = vec.contains("B");//结果:true
bool hasE = vec.contains("E");//结果:false
//2.indexOf(); 查找元素的索引(从前往后)
int index1 = vec.indexOf("C");//结果:2
int index2 = vec.indexOf("X");//结果:-1 ,表示没找到
//3.LastIndexof(); 查找元素的索引(从后往前)
vec.append("B");
int lastIndex = vec.lastIndexOf("B");//结果:4
//4.判断是否为空
bool IsEmpty = vec.isEmpty();//结果为:false
vec.clear();
bool IsEmpty1 = vec.isEmpty();//结果为:true
3. 迭代器遍历
QVector 支持多种遍历方式
QVector<int> vec = { 1,2,3,4,5 }; qDebug(); //方法1:Java风格迭代器,QT特有,不那么常用 QVectorIterator<int> i(vec); while (i.hasNext()) { qDebug() << i.next(); } // 方法 2: STL 风格迭代器 (更现代,推荐) for (auto it = vec.begin(); it != vec.end(); ++it) { qDebug() << *it; } // 方法 3: 基于范围的 for 循环 (C++11,最简洁) for (const auto& value : vec) { qDebug() << value; } // 方法 4: 使用索引 (最直接) for (int i = 0; i < vec.size(); ++i) { qDebug() << vec[i]; } // 方法 5: 使用 Qt 的 foreach 宏 (旧式,不推荐在新代码中使用) foreach(const int& value, vec) { qDebug() << value; }
4. 重要特性:隐式共享 (Implicit Sharing)
这是 Qt 容器一个非常强大的特性,也叫“写时复制”。
-
核心思想: 当多个
QVector对象赋值给彼此或作为参数传递时,它们并不会立即复制数据,而是共享同一份数据。只有当其中一个对象需要修改数据时(“写”操作),才会真正执行复制。 -
好处: 极大地提高了传递值的效率,避免了不必要的深度拷贝,同时又保持了值语义的简洁性。
QVector<int> v1(1000000, 42); // 一个包含100万个元素的大向量 QVector<int> v2 = v1; // 此时 v1 和 v2 共享同一份数据,开销极小 // 当修改 v2 时,才会发生真正的数据复制 v2[0] = 100; // 写操作触发“写时复制”,现在 v1 和 v2 拥有各自独立的数据

浙公网安备 33010602011771号