QT QHash的一点信息异常?BUG?

BUG复现代码

PS:Command 是一个结构体,里面有名为cs的属性;

    //test
    QHash<int, Command>testHash;
    Command cmd;
    testHash.insert(1, cmd);
    while (true)
    {
        qDebug() <<testHash.size()<<  testHash[1].cs << testHash.size();//①
        //qDebug() << testHash.value(1).cs << testHash.size();//②
        if (testHash.contains(1))//③
        {
            qDebug() << "testHash.contains(1)=true;";
            testHash.remove(1);
            continue;
        }
        else
        {
             break;
        }
    }

上述代码,①打印时testHash.size() 的值为0;但是③会一直成立;

问题出在testHash[1]。但为什么会出来testHash.size() 的值为0,但testHash.contains(1)却成立,待研究。

续:有网友执行相同的代码,①处有的人打印是0,testHash[1].cs,1;有的打印是1,testHash[1].cs,1;而我是0,testHash[1].cs,0;鉴于些,有人提出,不同的结果应该有所用的QT库、C++版本有关。

PS:后来我同时打开打印①②,在②出,size()的值是1;

<think>好的,用户现在想了解Qt中的qHash函数。我需要先回忆一下qHash的相关知识。qHashQt中用于为类型生成哈希值的函数,常用于QHash、QSet等容器。用户可能在使用这些容器时遇到了问题,或者需要自定义类型的哈希实现。 首先,我需要解释qHash的基本作用,比如它是如何支持哈希表的,返回类型是uint。然后,可能需要介绍Qt内置支持的类型的qHash,比如基本类型、QString、QByteArray等,用户可能想知道哪些类型可以直接使用而无需自己实现。 接下来,用户可能需要自定义类型的哈希函数,所以需要给出自定义qHash的方法,包括全局函数和成员函数两种方式。这里要强调必须将qHash放在同一个命名空间里,尤其是使用ADL查找的情况。可能需要示例代码来说明如何正确实现,比如一个简单的Person类,包含姓名和年龄,然后展示如何为它编写qHash函数。 另外,用户可能关心性能优化的问题,比如如何高效组合多个字段的哈希值。这里需要提到使用位运算或者QtqHashBits、qHashRange等函数。同时,需要注意哈希冲突的问题,虽然无法完全避免,但可以通过合理设计减少冲突。 用户可能还会问到qHash的注意事项,比如一致性(如果两个对象相等,它们的哈希值必须相同),以及何时需要自定义qHash,比如当类型包含指针或动态分配的内存时,可能需要自定义哈希逻辑。 可能用户在使用QHash或QSet时遇到了错误,提示没有合适的qHash函数,这时候需要检查是否为目标类型正确实现了qHash,并且是否在正确的命名空间中。此外,需要提醒用户确保哈希函数的性能,避免过于复杂的计算影响程序效率。 最后,总结qHash的重要性,强调在自定义类型时正确实现qHash的必要性,以及如何利用Qt提供的工具函数来简化实现过程。同时,可能建议用户在遇到性能问题时,考虑哈希函数的质量和效率。</think>以下是对Qt框架中`qHash`函数的逐步解析: ### 1. 核心作用 `qHash`是Qt框架中用于生成哈希值的核心函数,公式表达其基本行为: $$ \text{哈希值} = qHash(key, seed) $$ - 关键应用场景:`QHash`, `QSet`等哈希容器的底层实现 - 返回类型:`uint`(32位无符号整数) ### 2. 内置支持类型 Qt已为常见类型提供默认实现: ```cpp // 基本类型 qHash(bool) qHash(int) qHash(double) // Qt核心类型 qHash(const QString&) qHash(const QByteArray&) qHash(QLatin1StringView) ``` ### 3. 自定义类型实现 #### 方法一:全局函数(推荐) ```cpp namespace MyNamespace { class Person { public: QString name; int age; }; uint qHash(const Person &p, uint seed = 0) noexcept { // 组合成员哈希值 return qHashMulti(seed, p.name, p.age); } } ``` #### 方法二:成员函数(需配合ADL) ```cpp class Book { public: uint hash(uint seed) const noexcept { return qHash(title) ^ qHash(isbn); } private: QString title; QString isbn; }; uint qHash(const Book &b, uint seed = 0) noexcept { return b.hash(seed); } ``` ### 4. 关键规则 1. **一致性要求**: $$ a == b \Rightarrow qHash(a) == qHash(b) $$ 2. **冲突率**:应尽量降低不同对象产生相同哈希值的概率 3. **性能要求**:计算速度直接影响哈希容器操作效率 ### 5. 高级工具函数 #### 组合多个字段 ```cpp // 顺序敏感的组合方式 qHashMulti(seed, field1, field2...) // 顺序不敏感的组合方式 qHashMultiCommutative(seed, field1, field2...) ``` #### 内存块哈希 ```cpp qHashBits(const void *p, size_t len, uint seed = 0) ``` #### 范围哈希 ```cpp qHashRange(begin_iterator, end_iterator, seed = 0) ``` ### 6. 典型示例 ```cpp struct GeoCoordinate { double latitude; double longitude; int altitude; }; uint qHash(const GeoCoordinate &c, uint seed = 0) noexcept { // 使用Qt提供的组合函数(顺序敏感) return qHashMulti(seed, qHash(c.latitude), qHash(c.longitude), c.altitude); } // 使用示例 QSet<GeoCoordinate> locationSet; locationSet.insert({39.9042, 116.4074, 43}); ``` ### 7. 性能优化技巧 1. **预处理关键字段**:对字符串等复杂类型预先计算哈希 2. **避免碰撞热点**:对枚举类等小范围值添加随机种子 ```cpp qHash(enumValue) ^ qHash(seed) ``` 3. **利用缓存**:对不变对象可缓存哈希值 ### 8. 调试建议 当出现`no matching function for call to 'qHash'`错误时: 1. 确认函数签名正确 2. 检查是否在相同命名空间 3. 验证是否包含必要头文件 4. 确保没有歧义的重载 ### 9. 版本变化 | Qt版本 | 重要变化 | |--------|----------| | 5.0 | 引入`seed`参数 | | 6.0 | 强制`noexcept`修饰 |
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值