Qt Essential Classes
目录
QVariant
QFlags
QRandomGenerator
经典的Qt容器
QVector
QList
QMap
QMultiMap
QSet
QHash
QVariant
同std::variant是一样的,他是一个更加高级的union。在一个时间下,它虽然实际上只能是一种类型,但是一个variant可以hold住所有的types(因为本质上都是内存块塞0和1,理解这一点的同志们直接看API就完事了),这样,我们直接就可以存储一个通用的类型,对于不同的场景做对应的转换就好了!我的另一个意思是:提供了一个统一的接口来处理各种数据类型。QVariant
可以存储简单的数据类型(如整型、浮点型、字符串等)以及复杂的数据类型(如自定义类、列表等)。
方法 | 描述 |
---|---|
QVariant() | 默认构造函数,创建一个无效的 QVariant。 |
QVariant(const QVariant &other) | 拷贝构造函数。 |
QVariant(QVariant &&other) | 移动构造函数。 |
QVariant &operator=(const QVariant &other) | 赋值操作符。 |
QVariant &operator=(QVariant &&other) | 移动赋值操作符。 |
bool isValid() const | 检查 QVariant 是否有效。 |
bool isNull() const | 检查 QVariant 是否为空。 |
int type() const | 返回存储数据的类型。 |
QString typeName() const | 返回存储数据类型的名称。 |
template<typename T> | T value() :将 QVariant 转换为指定类型。 |
void clear() | 清除存储的数据。 |
static QVariant fromValue(const T &value) | 从值创建 QVariant。 |
template<typename T> | static T fromVariant(const QVariant &variant) :从 QVariant 获取值。 |
QVariantList toList() const | 将 QVariant 转换为 QVariantList(如有必要)。 |
QVariantMap toMap() const | 将 QVariant 转换为 QVariantMap(如有必要)。 |
试一手:
#include <QVariant> #include <QString> #include <QDebug> int main() {QVariant variant; // 存储整数variant = 42;qDebug() << "Stored integer:" << variant.toInt(); // 存储字符串variant = QString("Hello, QVariant!");qDebug() << "Stored string:" << variant.toString(); // 检查类型if (variant.type() == QVariant::String) {qDebug() << "Variant holds a string.";} // 使用 fromValue 和 toVariantQVariant doubleVariant = QVariant::fromValue(3.14);double value = doubleVariant.value<double>();qDebug() << "Stored double:" << value; return 0; }
QFlags
这个笔者感悟比较深:他在你设置一些对象的属性的时候很管用:它通过位运算提供了一种简单而高效的方式来组合多个标志。QFlags
主要用于处理枚举类型的标志组合,使得代码更加清晰和易于维护。
笔者建议你按照std::bitset的一个高级抽象来理解。我们实际上就是使用比特表达信息!完事!
方法 | 描述 |
---|---|
QFlags() | 默认构造函数,创建一个无效的 QFlags 对象。 |
QFlags(Flags f) | 构造函数,使用给定的标志初始化 QFlags 对象。 |
QFlags(const QFlags &other) | 拷贝构造函数。 |
QFlags(QFlags &&other) | 移动构造函数。 |
QFlags &operator=(const QFlags &other) | 赋值操作符。 |
QFlags &operator=(QFlags &&other) | 移动赋值操作符。 |
QFlags operator|(const QFlags &other) const | 或操作符,用于实现位或操作符,允许将两个 QFlags 对象的标志组合在一起。这个操作符返回一个新的 QFlags 对象,包含了两个原对象的所有标志。 |
QFlags operator&(const QFlags &other) const | 位与操作符,用于获取共同标志。 |
QFlags operator^(const QFlags &other) const | 位异或操作符,用于获取不共同的标志。 |
QFlags operator~() const | 位非操作符,反转当前标志。 |
bool testFlag(Flags f) const | 测试特定标志是否被设置。 |
QFlags& operator|=(const QFlags &other) | 赋值操作 |
QFlags& operator&=(const QFlags &other) | 复合位与赋值操作符。 |
QFlags& operator^=(const QFlags &other) | 复合位异或赋值操作符。 |
static QFlags fromValue(int value) | 从整数值创建 QFlags 对象。 |
#include <QCoreApplication> #include <QFlags> #include <QDebug> enum MyFlags {FlagA = 0x1, // 0001FlagB = 0x2, // 0010FlagC = 0x4 // 0100 }; Q_DECLARE_FLAGS(MyFlagSet, MyFlags) int main(int argc, char *argv[]) {QCoreApplication a(argc, argv); // 创建标志MyFlagSet flags;flags |= FlagA; // 添加 FlagAflags |= FlagB; // 添加 FlagB // 检查标志if (flags.testFlag(FlagA)) {qDebug() << "FlagA is set.";} if (flags.testFlag(FlagB)) {qDebug() << "FlagB is set.";} // 组合标志MyFlagSet moreFlags = FlagB | FlagC; // 组合 FlagB 和 FlagCflags |= moreFlags; // 添加组合的标志 // 输出当前标志状态qDebug() << "Current flags:" << flags; // 测试 FlagC 是否被设置if (flags.testFlag(FlagC)) {qDebug() << "FlagC is set.";} // 使用位与操作获取共同标志MyFlagSet commonFlags = flags & moreFlags;qDebug() << "Common flags:" << commonFlags; return a.exec(); } Q_DECLARE_METATYPE(MyFlagSet)
QRandomGenerator
这个玩意是检验你是Qt6选手还是Qt5选手的标准类。他就是qt5的qrand()的高级版,提供了一系列方法来生成均匀分布和正态分布的随机数,支持多种数据类型。QRandomGenerator
是线程安全的,因此可以在多线程环境中安全使用。
-
性能:高效生成随机数,适合需要大量随机数的应用场景。
-
可移植性:在不同平台上具有一致的行为。
-
种子控制:支持通过种子初始化生成器,以便于生成可重复的随机数序列。
-
随机数分布:支持生成均匀分布、正态分布等类型的随机数。
方法 | 描述 |
---|---|
QRandomGenerator() | 默认构造函数,使用当前时间作为种子。 |
QRandomGenerator(uint seed) | 使用指定种子初始化生成器。 |
static QRandomGenerator *global() | 返回全局的随机数生成器实例。 |
int bounded(int range) | 生成一个在 [0, range) 范围内的随机整数。 |
double generateDouble() | 生成一个在 [0.0, 1.0) 范围内的随机浮点数。 |
int generateInt() | 生成一个随机整数。 |
void seed(uint seed) | 设置生成器的种子。 |
static void globalSeed(uint seed) | 设置全局随机数生成器的种子。 |
#include <QCoreApplication> #include <QRandomGenerator> #include <QDebug> int main(int argc, char *argv[]) {QCoreApplication a(argc, argv); // 创建一个 QRandomGenerator 实例QRandomGenerator *generator = QRandomGenerator::global(); // 生成 10 个随机整数qDebug() << "Random integers:";for (int i = 0; i < 10; ++i) {int randomInt = generator->bounded(100); // 在 [0, 100) 范围内qDebug() << randomInt;} // 生成 10 个随机浮点数qDebug() << "Random doubles:";for (int i = 0; i < 10; ++i) {double randomDouble = generator->generateDouble(); // 在 [0.0, 1.0) 范围内qDebug() << randomDouble;} return a.exec(); }
经典的Qt容器
QVector
QVector
是 Qt 提供的一种动态数组容器,类似于 C++ 标准库中的 std::vector
。它用于存储同一类型的元素,并支持快速的随机访问、插入和删除操作。QVector
主要用于需要动态调整大小且频繁读取元素的场景。
是的,就是std::vector的Qt版本。笔者在《Qt高性能编程》中见到过观点:use std rather than qt,这个事情仁者见仁智者见智。笔者认为按照场景使用最好。
-
动态大小:
QVector
可以根据需要自动扩展或收缩。 -
快速随机访问:可以通过索引快速访问元素,访问时间复杂度为 O(1)。
-
连续内存存储:数据在内存中是连续存储的,能更好地利用 CPU 缓存,提高性能。
-
支持多种数据类型:可以存储任意类型的数据,通常与 Qt 的其他类型(如
QVariant
)结合使用。 -
高效的内存管理:通过智能的内存分配策略减少内存碎片。
方法 | 描述 |
---|---|
QVector<T>() | 默认构造函数,创建一个空的 QVector 。 |
QVector<T>(int size) | 创建一个指定大小的 QVector ,元素初始化为 T() 。 |
QVector<T>(const QVector<T> &other) | 拷贝构造函数,复制另一个 QVector 的内容。 |
~QVector() | 析构函数,释放内存。 |
T& operator[](int index) | 返回指定索引处的元素的引用。 |
const T& operator[](int index) const | 返回指定索引处的元素的常量引用。 |
int size() const | 返回当前元素的数量。 |
bool isEmpty() const | 判断 QVector 是否为空。 |
void append(const T &value) | 在 QVector 末尾添加一个新元素。 |
void prepend(const T &value) | 在 QVector 开头添加一个新元素。 |
void insert(int index, const T &value) | 在指定位置插入一个新元素。 |
void removeAt(int index) | 移除指定位置的元素。 |
void clear() | 清空 QVector 中的所有元素。 |
T takeAt(int index) | 移除并返回指定位置的元素。 |
void resize(int size) | 调整 QVector 的大小,增加或减少元素数量。 |
T& first() | 返回第一个元素的引用。 |
T& last() | 返回最后一个元素的引用。 |
QVector<T> mid(int pos, int length = -1) const | 返回从 pos 开始的子数组。 |
QVector<T> &operator=(const QVector<T> &other) | 赋值运算符,复制另一个 QVector 的内容。 |
bool operator==(const QVector<T> &other) const | 判断两个 QVector 是否相等。 |
#include <QVector> #include <QDebug> int main() {// 创建一个空的 QVectorQVector<int> vec; // 添加元素vec.append(10);vec.append(20);vec.append(30);// 输出当前大小qDebug() << "Size:" << vec.size(); // Size: 3 // 访问元素qDebug() << "First element:" << vec.first(); // First element: 10 // 插入元素vec.insert(1, 15);// 输出元素for (int i = 0; i < vec.size(); ++i) {qDebug() << vec[i]; // 10 15 20 30} // 移除元素vec.removeAt(2); // 移除元素 20 // 清空 QVectorvec.clear();// 检查是否为空qDebug() << "Is empty:" << vec.isEmpty(); // Is empty: true return 0; }
它的数据结构特点:
-
访问速度:因为数据是连续存储的,所以
QVector
的访问速度通常比链表等非连续存储的数据结构快。 -
插入和删除:虽然在末尾插入和删除操作的时间复杂度为 O(1),但在中间位置插入和删除的时间复杂度为 O(n),这要注意。
它的常见的使用场景:
-
动态数据集合:当需要一个大小可变的数组来存储数据时,例如用户输入、实时数据流等。
-
临时存储:处理算法时使用的临时数据,例如排序、搜索等。
-
图形界面:在 Qt 应用中,常用于存储 UI 组件、图形对象等。
QList
注意在Qt6下,QList == QVector,这里是给Qt5看的:
QList实际上更加的智能,这点随了Java的List:原生类型存数值,复杂类型存指针。但是注意,QList仍然是连续的。比起来,QLinkedList确实是真正的链表!这点请所有使用链表的客户程序员注意!使用链表是QLinkedList!
QList<T>() | 默认构造函数,创建一个空的 QList 。 |
---|---|
QList<T>(int size) | 创建一个指定大小的 QList ,元素初始化为 T() 。 |
QList<T>(const QList<T> &other) | 拷贝构造函数,复制另一个 QList 的内容。 |
~QList() | 析构函数,释放内存。 |
T& operator[](int index) | 返回指定索引处的元素的引用。 |
const T& operator[](int index) const | 返回指定索引处的元素的常量引用。 |
int size() const | 返回当前元素的数量。 |
bool isEmpty() const | 判断 QList 是否为空。 |
void append(const T &value) | 在 QList 末尾添加一个新元素。 |
void prepend(const T &value) | 在 QList 开头添加一个新元素。 |
void insert(int index, const T &value) | 在指定位置插入一个新元素。 |
void removeAt(int index) | 移除指定位置的元素。 |
void clear() | 清空 QList 中的所有元素。 |
T takeAt(int index) | 移除并返回指定位置的元素。 |
T& first() | 返回第一个元素的引用。 |
T& last() | 返回最后一个元素的引用。 |
QList<T> mid(int pos, int length = -1) const | 返回从 pos 开始的子列表。 |
QList<T> &operator=(const QList<T> &other) | 赋值运算符,复制另一个 QList 的内容。 |
bool operator==(const QList<T> &other) const | 判断两个 QList 是否相等。 |
#include <QList> #include <QDebug> int main() {// 创建一个空的 QListQList<int> list; // 添加元素list.append(10);list.append(20);list.append(30); // 输出当前大小qDebug() << "Size:" << list.size(); // Size: 3 // 访问元素qDebug() << "First element:" << list.first(); // First element: 10 // 插入元素list.insert(1, 15);// 输出元素for (int i = 0; i < list.size(); ++i) {qDebug() << list[i]; // 10 15 20 30} // 移除元素list.removeAt(2); // 移除元素
QMap
QMap
是 Qt 提供的一种基于红黑树的关联容器,主要用于存储键值对。它类似于 C++ 标准库中的 std::map
,但在使用上更加方便,特别是在与 Qt 其他类的结合使用时。QMap
提供了快速的查找、插入和删除操作,同时能够保持键的有序性。
-
有序性:
QMap
中的键是自动排序的,因此可以根据键的顺序遍历元素。 -
快速查找:使用红黑树实现,查找、插入和删除的平均时间复杂度为 O(log n)。
-
多类型支持:可以存储任意类型的键值对,通常与 Qt 的其他类型(如
QString
,QVariant
)结合使用。 -
重复键处理:
QMap
不允许重复的键,如果插入一个已存在的键,原有的值将被覆盖。 -
易于使用的 API:提供了丰富的方法来操作键值对,方便开发者管理数据。
方法 | 描述 |
---|---|
QMap<Key, T>() | 默认构造函数,创建一个空的 QMap 。 |
QMap<Key, T>(const QMap<Key, T> &other) | 拷贝构造函数,复制另一个 QMap 的内容。 |
~QMap() | 析构函数,释放内存。 |
int size() const | 返回当前键值对的数量。 |
bool isEmpty() const | 判断 QMap 是否为空。 |
void insert(const Key &key, const T &value) | 插入一个键值对,如果键已存在,值将被覆盖。 |
T value(const Key &key, const T &defaultValue = T()) const | 返回指定键的值,如果键不存在则返回默认值。 |
void remove(const Key &key) | 移除指定键的元素。 |
bool contains(const Key &key) const | 判断是否包含指定的键。 |
QList<Key> keys() const | 返回所有键的列表。 |
QList<T> values() const | 返回所有值的列表。 |
QList<T> values(const Key &key) const | 返回指定键对应的值的列表。 |
Key firstKey() const | 返回第一个键。 |
Key lastKey() const | 返回最后一个键。 |
void clear() | 清空 QMap 中的所有键值对。 |
QMap<Key, T> &operator=(const QMap<Key, T> &other) | 赋值运算符,复制另一个 QMap 的内容。 |
bool operator==(const QMap<Key, T> &other) const | 判断两个 QMap 是否相等。 |
#include <QMap> #include <QString> #include <QDebug> int main() {QMap<QString, int> grades; // 插入键值对grades.insert("Alice", 85);grades.insert("Bob", 90);grades.insert("Charlie", 78); // 输出总数qDebug() << "Total students:" << grades.size(); // Total students: 3 // 获取某个学生的成绩qDebug() << "Alice's grade:" << grades.value("Alice"); // Alice's grade: 85 // 修改成绩grades["Alice"] = 95; // 更新 Alice 的成绩qDebug() << "Alice's updated grade:" << grades.value("Alice"); // Alice's updated grade: 95 // 检查某个学生是否存在if (grades.contains("David")) {qDebug() << "David's grade:" << grades.value("David");} else {qDebug() << "David not found."; // David not found.} // 移除某个学生grades.remove("Charlie"); // 输出所有学生的成绩for (const QString &name : grades.keys()) {qDebug() << name << ":" << grades.value(name);} // 清空 QMapgrades.clear();qDebug() << "Is empty:" << grades.isEmpty(); // Is empty: true return 0; }
QMap
的性能在大多数场景下都非常优秀。由于采用红黑树实现,其查找、插入和删除操作的平均时间复杂度为 O(log n)。虽然在某些情况下,QMap
的性能可能略逊于 QHash
(哈希表实现),但在需要有序存储时,QMap
是更好的选择。
QMap
的使用场景非常广泛,包括但不限于:
-
配置存储:存储配置信息时,可以使用键值对的形式存储各类配置项,便于查找和修改。
-
数据索引:在需要根据某种键(如 ID、名称)快速查找数据时,使用
QMap
可以高效地管理这些关系。 -
有序数据:在需要保持元素顺序的同时又要快速查找和修改的场合,
QMap
是一个理想的选择。
QMultiMap
QMultiMap
是 Qt 提供的一种特殊的关联容器,允许多个值与同一个键关联。它类似于 QMap
,但不同之处在于 QMultiMap
允许键的重复,适合于需要存储多个值而不想丢失键的场景。
-
允许重复键:
QMultiMap
允许多个值与同一个键关联,适合存储一对多关系的数据。 -
自动排序:与
QMap
一样,QMultiMap
中的键是自动排序的,能够根据键的顺序遍历元素。 -
快速查找:基于红黑树实现,查找、插入和删除的平均时间复杂度为 O(log n)。
-
多类型支持:支持存储任意类型的键值对,通常与 Qt 的其他类型(如
QString
,QVariant
)结合使用。 -
易于使用的 API:提供了丰富的方法来操作键值对,方便开发者管理数据。
方法 | 描述 |
---|---|
QMultiMap<Key, T>() | 默认构造函数,创建一个空的 QMultiMap 。 |
QMultiMap<Key, T>(const QMultiMap<Key, T> &other) | 拷贝构造函数,复制另一个 QMultiMap 的内容。 |
~QMultiMap() | 析构函数,释放内存。 |
int size() const | 返回当前键值对的数量。 |
bool isEmpty() const | 判断 QMultiMap 是否为空。 |
void insert(const Key &key, const T &value) | 插入一个键值对,允许同一个键有多个值。 |
QList<T> values(const Key &key) const | 返回指定键对应的所有值的列表。 |
void remove(const Key &key) | 移除所有与指定键关联的元素。 |
bool contains(const Key &key) const | 判断是否包含指定的键。 |
QList<Key> keys() const | 返回所有键的列表。 |
Key firstKey() const | 返回第一个键。 |
Key lastKey() const | 返回最后一个键。 |
void clear() | 清空 QMultiMap 中的所有键值对。 |
QMultiMap<Key, T> &operator=(const QMultiMap<Key, T> &other) | 赋值运算符,复制另一个 QMultiMap 的内容。 |
bool operator==(const QMultiMap<Key, T> &other) const | 判断两个 QMultiMap 是否相等。 |
#include <QMultiMap> #include <QString> #include <QDebug> int main() {QMultiMap<QString, QString> studentCourses; // 插入多个值studentCourses.insert("Alice", "Math");studentCourses.insert("Alice", "Science");studentCourses.insert("Bob", "Math");studentCourses.insert("Charlie", "History");studentCourses.insert("Charlie", "Math"); // 输出每个学生的课程for (const QString &student : studentCourses.keys()) {QList<QString> courses = studentCourses.values(student);qDebug() << student << "is enrolled in:" << courses;} // 移除某个学生的所有课程studentCourses.remove("Alice"); // 检查是否存在if (!studentCourses.contains("Alice")) {qDebug() << "Alice has been removed from the course list.";} // 清空 QMultiMapstudentCourses.clear();qDebug() << "Is empty:" << studentCourses.isEmpty(); // Is empty: true return 0; }
QMultiMap
的性能与 QMap
类似,查找、插入和删除操作的平均时间复杂度为 O(log n)。由于它允许重复键的特性,在管理一对多关系时非常有效。
QMultiMap
适用于多种场景:
-
多对多关系存储:在需要存储一对多或多对多关系的数据时,
QMultiMap
是理想的选择。 -
分类数据:在需要将数据分类存储时,可以使用相同的键来代表不同的类别。
-
标签系统:在实现标签系统时,可以将多个标签与同一对象关联,方便管理和查询。
QSet
QSet
是 Qt 提供的一种集合容器,主要用于存储唯一值的集合。它类似于 C++ 标准库中的 std::set
,但在使用上更加方便,特别是在与 Qt 其他类的结合使用时。QSet
适合用于需要存储不重复元素的场景,提供快速的查找、插入和删除操作。
-
唯一性:
QSet
中的每个元素都是唯一的,不能存储重复的值。 -
无序性:元素在集合中没有特定的顺序,遍历时的顺序与插入顺序无关。
-
快速查找:基于哈希表实现,查找、插入和删除操作的平均时间复杂度为 O(1)。
-
多类型支持:可以存储任意类型的数据,通常与 Qt 的其他类型(如
QString
,QVariant
)结合使用。 -
易于使用的 API:提供了丰富的方法来操作集合,方便开发者管理数据。
方法 | 描述 |
---|---|
QSet<T>() | 默认构造函数,创建一个空的 QSet 。 |
QSet<T>(const QSet<T> &other) | 拷贝构造函数,复制另一个 QSet 的内容。 |
~QSet() | 析构函数,释放内存。 |
int size() const | 返回集合中元素的数量。 |
bool isEmpty() const | 判断 QSet 是否为空。 |
void insert(const T &value) | 向集合中添加一个新元素,如果元素已存在,则不进行操作。 |
void remove(const T &value) | 移除集合中的指定元素。 |
bool contains(const T &value) const | 判断集合是否包含指定元素。 |
QList<T> toList() const | 将集合转换为 QList 。 |
QSet<T> intersect(const QSet<T> &other) const | 返回与另一个集合的交集。 |
QSet<T> unite(const QSet<T> &other) const | 返回与另一个集合的并集。 |
QSet<T> subtract(const QSet<T> &other) const | 返回从集合中减去另一个集合后的结果。 |
void clear() | 清空集合中的所有元素。 |
QSet<T> &operator=(const QSet<T> &other) | 赋值运算符,复制另一个 QSet 的内容。 |
bool operator==(const QSet<T> &other) const | 判断两个 QSet 是否相等。 |
#include <QSet> #include <QString> #include <QDebug> int main() {QSet<QString> students; // 插入学生姓名students.insert("Alice");students.insert("Bob");students.insert("Charlie");students.insert("Alice"); // 重复插入,不会改变集合 // 输出当前学生人数qDebug() << "Total students:" << students.size(); // Total students: 3 // 检查是否包含某个学生if (students.contains("Bob")) {qDebug() << "Bob is in the set.";} // 移除某个学生students.remove("Charlie"); // 输出所有学生姓名for (const QString &name : students) {qDebug() << name;} // 清空集合students.clear();qDebug() << "Is empty:" << students.isEmpty(); // Is empty: true return 0; }
QHash
QHash
是 Qt 提供的一种基于哈希表的关联容器,主要用于存储键值对。它允许快速的查找、插入和删除操作,适合需要频繁访问数据的场景。与 QMap
不同的是,QHash
不会自动排序其元素,主要关注数据的存取效率。
-
键的唯一性:
QHash
中的每个键都是唯一的,不能存储重复的键。 -
无序性:元素在集合中没有特定的顺序,遍历时的顺序与插入顺序无关。
-
快速查找:基于哈希表实现,查找、插入和删除操作的平均时间复杂度为 O(1)。
-
多类型支持:可以存储任意类型的键值对,通常与 Qt 的其他类型(如
QString
,QVariant
)结合使用。 -
易于使用的 API:提供了丰富的方法来操作键值对,方便开发者管理数据。
方法 | 描述 |
---|---|
QHash<Key, T>() | 默认构造函数,创建一个空的 QHash 。 |
QHash<Key, T>(const QHash<Key, T> &other) | 拷贝构造函数,复制另一个 QHash 的内容。 |
~QHash() | 析构函数,释放内存。 |
int size() const | 返回当前键值对的数量。 |
bool isEmpty() const | 判断 QHash 是否为空。 |
void insert(const Key &key, const T &value) | 向哈希表中插入一个键值对,如果键已存在,则值将被覆盖。 |
void remove(const Key &key) | 移除指定键的元素。 |
bool contains(const Key &key) const | 判断是否包含指定的键。 |
T value(const Key &key, const T &defaultValue = T()) const | 返回指定键的值,如果键不存在则返回默认值。 |
QList<Key> keys() const | 返回所有键的列表。 |
QList<T> values() const | 返回所有值的列表。 |
void clear() | 清空 QHash 中的所有键值对。 |
QHash<Key, T> &operator=(const QHash<Key, T> &other) | 赋值运算符,复制另一个 QHash 的内容。 |
bool operator==(const QHash<Key, T> &other) const | 判断两个 QHash 是否相等。 |
cpp复制代码#include <QHash> #include <QString> #include <QDebug> int main() {QHash<QString, int> grades; // 插入学生成绩grades.insert("Alice", 85);grades.insert("Bob", 90);grades.insert("Charlie", 78); // 输出学生总数qDebug() << "Total students:" << grades.size(); // Total students: 3 // 获取某个学生的成绩qDebug() << "Alice's grade:" << grades.value("Alice"); // Alice's grade: 85 // 修改成绩grades["Alice"] = 95; // 更新 Alice 的成绩qDebug() << "Alice's updated grade:" << grades.value("Alice"); // Alice's updated grade: 95 // 检查某个学生是否存在if (grades.contains("David")) {qDebug() << "David's grade:" << grades.value("David");} else {qDebug() << "David not found."; // David not found.} // 移除某个学生grades.remove("Charlie"); // 输出所有学生的成绩for (const QString &name : grades.keys()) {qDebug() << name << ":" << grades.value(name);} // 清空 QHashgrades.clear();qDebug() << "Is empty:" << grades.isEmpty(); // Is empty: true return 0; }
QHash
适用于多种场景,例如:
-
数据索引:在需要根据某个键快速查找数据时,
QHash
是一个理想的选择。 -
缓存机制:可以使用
QHash
来实现简单的缓存机制,以存储计算结果或数据。 -
频率统计:在处理需要统计元素出现频率的场景时,
QHash
可以轻松存储和更新频率。
相关文章:
Qt Essential Classes
目录 QVariant QFlags QRandomGenerator 经典的Qt容器 QVector QList QMap QMultiMap QSet QHash QVariant 同std::variant是一样的,他是一个更加高级的union。在一个时间下,它虽然实际上只能是一种类型,但是一个variant可以hold住…...

小小猫棒onu替换家用光猫,薅运营商带宽羊毛,突破1000M
小小猫棒onu 一、总体步骤 1 记录原来光猫信息 主要包括SN,ploam密码,loid、loid密码、 mac、上网的vlan id等 一般gpon采用SN、ploam密码、SNploam密码三种中的一种认证方式 一般Epon采用loid(逻辑id)、mac、loid mac三种中…...

软件测试学习笔记丨Selenium学习笔记:css定位
本文转自测试人社区,原文链接:https://ceshiren.com/t/topic/22511 本文为霍格沃兹测试开发学社的学习经历分享,写出来分享给大家,希望有志同道合的小伙伴可以一起交流技术,一起进步~ 说明:本篇博客基于sel…...
python数据处理常用操作
数据处理是机器学习中非常重要的一步,以下是一些常用的操作和示例代码: 1. 数据清洗 处理缺失值: import pandas as pd# 读取数据 df pd.read_csv(data.csv)# 删除缺失值 df.dropna(inplaceTrue)# 用均值填充缺失值 df.fillna(df.mean(), i…...
解决minio跨域问题
MinIO 支持跨域资源共享(CORS),允许你配置跨域请求的相关策略。以下是一个基本的CORS配置示例,你可以在MinIO的配置文件(例如config.json)中设置这些策略: 在Linux中 root/.minio 目录下如果没有就新建一个 config.jso…...
python 跳过当前循环
在 Python 中,可以使用 continue 语句来跳过当前循环的剩余部分,并继续下一次循环。continue 语句用于跳过循环体中剩余的语句,并立即开始下一次迭代。 以下是一个简单的示例,演示了如何在 for 循环中使用 continue 语句…...

数据库数据恢复—Oracle ASM磁盘组掉线 ,ASM实例无法挂载的数据恢复案例
Oracle数据库数据恢复环境&故障: Oracle ASM磁盘组由4块磁盘组成。Oracle ASM磁盘组掉线 ,ASM实例不能mount。 Oracle数据库故障分析&恢复方案: 数据库数据恢复工程师对组成ASM磁盘组的磁盘进行分析。对ASM元数据进行分析发现ASM存储…...

jupyter notebook改变默认启动路径
安装好Anaconda 3以后,就可以使用Jupyter notebook了,但是我们打开Jupyter notebook后,发现界面是一个默认的目录,这个目录在哪里?如果想把自己写的程序文件保存在自己新建的一个文件夹里,修改默认目录到自…...

libevent源码剖析-基本数据结构
1 简介 前面系列文章对libevent源码的主体结构,从reactor框架实现,到evbuffer和bufferevent实现原理,及libevent的例子进行了剖析,自此,我们便可基于libevent开发app了。 从本文开始,主要来介绍下libevent源…...

往期文章汇总——射频测量+无线通信+软件无线电+6G科普
本节目录 一、射频测量系列往期链接 二、无线通信系列往期链接 三、软件无线电系列往期链接 四、6G科普系列往期链接本节内容 一、射频测量系列往期链接 射频测量 | 滤波器的关注指标 射频测量 | 射频电路中的负载与滤波器 射频测量 | 射频衰减器的功率系数 射频测量 | 衰减…...
微信小程序 - 深 / 浅拷贝实现方法,微信小程序深拷贝与浅拷贝,函数方法封装直接调用使用,深拷贝cloneDeep和浅拷贝clone(深复制和浅复制)
前言 在微信小程序中,你无法 直接使用常规浏览器环境中的深浅拷贝方法。 但可以借助 utils.js 实现,下面是方法。 创建深浅拷贝函数 依次打开小程序目录【utils】→【utils.js】,写入深拷贝函数并暴露出去。 // utils.js// 对象深拷贝函数 const deepClone = function(in…...

Log4Net配置详解及输出自定义消息类示例代码
1.简单使用实例 1.1 添加log4net.dll的引用。 在NuGet程序包中搜索log4net并添加,此次我所用版本为2.0.17。如下图: 1.2 添加配置文件 右键项目,添加新建项,搜索选择应用程序配置文件,命名为log4net.config,…...

C++在实际项目中的应用第二节:C++与区块链
第五章:C在实际项目中的应用 第二课:C与区块链 区块链技术因其去中心化、不可篡改和透明性而受到广泛关注。在这门课程中,我们将深入探讨区块链的基本原理、智能合约的开发以及实际应用的案例分析,重点使用 C 作为实现语言&…...

浅记React面试丢人时刻
前提 去面试了,技术面完一轮之后,突发的来了一次React的考察,哥们,猝不及防之下,脑袋直接清空,啥也想不起来了。现在想想,实属丢人,记录一下啥也没答出来的面试,钉在耻辱…...

Python入门:学会Python装饰器让你的代码如虎添翼!(Python如何不改动原有函数代码添加一些额外的功能)
文章目录 📖 介绍 📖🏡 演示环境 🏡📒 文章内容 📒📝 什么是Python装饰器📝 如何编写Python装饰器📝 带参数的装饰器📝 Python装饰器的使用场景📝 注意事项📝 多装饰器的使用⚓️ 相关链接 ⚓️📖 介绍 📖 你是不是在写代码的时候,常常会想有没有…...

【C++】哈希冲突的解决办法:闭散列 与 开散列
哈希冲突解决 上一篇博客提到了,哈希函数的优化可以减小哈希冲突发生的可能性,但无法完全避免。本文就来探讨一下解决哈希冲突的两种常见方法:闭散列和开散列 1.闭散列 闭散列也叫开放定址法,发生哈希冲突时,如果哈…...

复刻系列-原神 5.1 版本先行展示页
复刻原神 5.1 版本先行展示页 0. 视频 BilBil站视频演示 复刻-原神5.1版本先行展示页 1. 基本信息 作者: 啊是特嗷桃系列: 复刻系列官方的网站: 《原神》官方网站-全新5.1版本「命定将焚的虹光」上线!复刻的网站: 《原神》复刻网站-全新5.1版本「命定将焚的虹光」…...

STM32 第3章 如何用串口下载程序
时间:2024.10.28 一、学习内容 1、安装USB转串口驱动 1.1串口下载连接示意图 1、USB转串口模块在开发板上是一个独立的模块,可通过调帽与其他串口连接,USART1/2/3/4/5 2、只有USART1才具有串口下载的功能。 3、CH340是电平转换芯片,将电脑端输出的USB电平和单片机输…...

HT71782 20V,15A全集成同步升压转换器
1、特征 输入电压范围VN:2.7V-20V 输出电压范围VouT:4.5V-20V 可编程峰值电流:15A 高转换效率: 93%(VIN7.4V,VoUT15.5V,IouT 1.5A) 轻载条件下两种调制方式:脉频调制(PFM)和 强制脉宽调试(FPWM) 支持两种tr/t模式,应对EMI挑战 低关断功耗,关断电流1uA 可…...

[含文档+PPT+源码等]精品基于PHP实现的培训机构信息管理系统的设计与实现
基于PHP实现的培训机构信息管理系统的设计与实现背景,可以从以下几个方面进行阐述: 一、社会发展与教育需求 随着经济的不断发展和人口数量的增加,教育培训行业迎来了前所未有的发展机遇。家长对子女教育的重视程度日益提高,课外…...
PHP和Node.js哪个更爽?
先说结论,rust完胜。 php:laravel,swoole,webman,最开始在苏宁的时候写了几年php,当时觉得php真的是世界上最好的语言,因为当初活在舒适圈里,不愿意跳出来,就好比当初活在…...
在四层代理中还原真实客户端ngx_stream_realip_module
一、模块原理与价值 PROXY Protocol 回溯 第三方负载均衡(如 HAProxy、AWS NLB、阿里 SLB)发起上游连接时,将真实客户端 IP/Port 写入 PROXY Protocol v1/v2 头。Stream 层接收到头部后,ngx_stream_realip_module 从中提取原始信息…...
linux 下常用变更-8
1、删除普通用户 查询用户初始UID和GIDls -l /home/ ###家目录中查看UID cat /etc/group ###此文件查看GID删除用户1.编辑文件 /etc/passwd 找到对应的行,YW343:x:0:0::/home/YW343:/bin/bash 2.将标红的位置修改为用户对应初始UID和GID: YW3…...
什么?连接服务器也能可视化显示界面?:基于X11 Forwarding + CentOS + MobaXterm实战指南
文章目录 什么是X11?环境准备实战步骤1️⃣ 服务器端配置(CentOS)2️⃣ 客户端配置(MobaXterm)3️⃣ 验证X11 Forwarding4️⃣ 运行自定义GUI程序(Python示例)5️⃣ 成功效果
Java面试专项一-准备篇
一、企业简历筛选规则 一般企业的简历筛选流程:首先由HR先筛选一部分简历后,在将简历给到对应的项目负责人后再进行下一步的操作。 HR如何筛选简历 例如:Boss直聘(招聘方平台) 直接按照条件进行筛选 例如:…...

Mac下Android Studio扫描根目录卡死问题记录
环境信息 操作系统: macOS 15.5 (Apple M2芯片)Android Studio版本: Meerkat Feature Drop | 2024.3.2 Patch 1 (Build #AI-243.26053.27.2432.13536105, 2025年5月22日构建) 问题现象 在项目开发过程中,提示一个依赖外部头文件的cpp源文件需要同步,点…...
大语言模型(LLM)中的KV缓存压缩与动态稀疏注意力机制设计
随着大语言模型(LLM)参数规模的增长,推理阶段的内存占用和计算复杂度成为核心挑战。传统注意力机制的计算复杂度随序列长度呈二次方增长,而KV缓存的内存消耗可能高达数十GB(例如Llama2-7B处理100K token时需50GB内存&a…...

Linux 内存管理实战精讲:核心原理与面试常考点全解析
Linux 内存管理实战精讲:核心原理与面试常考点全解析 Linux 内核内存管理是系统设计中最复杂但也最核心的模块之一。它不仅支撑着虚拟内存机制、物理内存分配、进程隔离与资源复用,还直接决定系统运行的性能与稳定性。无论你是嵌入式开发者、内核调试工…...
LangChain知识库管理后端接口:数据库操作详解—— 构建本地知识库系统的基础《二》
这段 Python 代码是一个完整的 知识库数据库操作模块,用于对本地知识库系统中的知识库进行增删改查(CRUD)操作。它基于 SQLAlchemy ORM 框架 和一个自定义的装饰器 with_session 实现数据库会话管理。 📘 一、整体功能概述 该模块…...
【Android】Android 开发 ADB 常用指令
查看当前连接的设备 adb devices 连接设备 adb connect 设备IP 断开已连接的设备 adb disconnect 设备IP 安装应用 adb install 安装包的路径 卸载应用 adb uninstall 应用包名 查看已安装的应用包名 adb shell pm list packages 查看已安装的第三方应用包名 adb shell pm list…...