QHash <Key,T>是Qt的通用容器類之一。它存儲(chǔ)(鍵,值)對(duì),并提供與鍵關(guān)聯(lián)的值的快速查找。
1,QHash提供與QMap非常相似的功能。
不同之處在于:
(1)QHash提供比QMap更快的查找,但所需空間更大。
(2)QMap默認(rèn)按照鍵值升序排序;。使用QHash按照鍵值任意排序。
(3)QMap的鍵類型必須提供operator <()。QHash的鍵類型必須提供operator ==()和稱為qHash()的全局哈希函數(shù)。
2,一個(gè)QHash每個(gè)鍵只允許一個(gè)值。
hash.insert("plenty", 100);hash.insert("plenty", 2000);// hash.value("plenty") == 2000
3,如果只需要從哈希中提取值(而不是鍵),則也可以使用foreach:
QHash<QString, int> hash;...foreach (int value, hash)cout << value << Qt::endl;
Qt進(jìn)入foreach循環(huán)時(shí)會(huì)自動(dòng)獲取容器的副本,如果在迭代時(shí)修改容器,則不會(huì)影響循環(huán)(如果不修改容器,則仍會(huì)進(jìn)行復(fù)制,但是由于隱式共享,復(fù)制容器非常快)。由于foreach會(huì)創(chuàng)建容器的副本,因此對(duì)變量使用非常量引用將不允許您修改原始容器,它只會(huì)影響副本。
Qt foreach循環(huán)的替代方法for是C ++ 11和更高版本中的基于范圍的。但是,基于范圍的for可能會(huì)強(qiáng)制Qt容器分離,而foreach不會(huì)。使用foreachAlways復(fù)制容器,對(duì)于STL容器通常并不容易。建議使用foreach Qt容器,并使用基于范圍的forSTL 容器。
4,qHash()函數(shù)
QHash的鍵類型除了是可分配的數(shù)據(jù)類型外,還具有其他要求:它必須提供operator ==(),并且該類型的名稱空間中還必須有一個(gè)qHash()函數(shù),該函數(shù)返回鍵類型的參數(shù)的哈希值。該qHash()函數(shù)計(jì)算基于密鑰的數(shù)值。只要給定相同的參數(shù),它總是返回相同的值,它就可以使用任何可以想象的算法。換句話說(shuō),如果e1 == e2,則qHash(e1) == qHash(e2)也必須成立。但是,為了獲得良好的性能,qHash()函數(shù)應(yīng)嘗試最大程度地為不同的鍵返回不同的哈希值。例如:
?
#ifndef EMPLOYEE_H
#define EMPLOYEE_Hclass Employee
{
public:Employee() {}Employee(const QString &name, QDate dateOfBirth);...private:QString myName;QDate myDateOfBirth;
};inline bool operator==(const Employee &e1, const Employee &e2)
{return e1.name() == e2.name()&& e1.dateOfBirth() == e2.dateOfBirth();
}inline uint qHash(const Employee &key, uint seed)
{return qHash(key.name(), seed) ^ key.dateOfBirth().day();
}#endif // EMPLOYEE_H
注意:如果是自定義類型或是第三方庫(kù)類型作為哈希表的鍵值時(shí),對(duì)perator ==()和qHash()函數(shù)的定義必須是全局的,要定義在使用QHash<K,T>之前,如果有命名空間,則是定義在命名空間之外的,否則qt模板函數(shù)是無(wú)法通過(guò)自定義模板::類名::qHash來(lái)調(diào)用自定義的哈希函數(shù),會(huì)出現(xiàn)如下錯(cuò)誤:
?error C2665: “qHash”: 25 個(gè)重載中沒(méi)有一個(gè)可以轉(zhuǎn)換所有參數(shù)類型? ?
?5,QHash實(shí)現(xiàn)的鍵值哈希函數(shù)
Q_CORE_EXPORT Q_DECL_PURE_FUNCTION uint qHashBits(const void *p, size_t size, uint seed = 0) Q_DECL_NOTHROW;Q_DECL_CONST_FUNCTION Q_DECL_CONSTEXPR inline uint qHash(char key, uint seed = 0) Q_DECL_NOTHROW { return uint(key) ^ seed; }
Q_DECL_CONST_FUNCTION Q_DECL_CONSTEXPR inline uint qHash(uchar key, uint seed = 0) Q_DECL_NOTHROW { return uint(key) ^ seed; }
Q_DECL_CONST_FUNCTION Q_DECL_CONSTEXPR inline uint qHash(signed char key, uint seed = 0) Q_DECL_NOTHROW { return uint(key) ^ seed; }
Q_DECL_CONST_FUNCTION Q_DECL_CONSTEXPR inline uint qHash(ushort key, uint seed = 0) Q_DECL_NOTHROW { return uint(key) ^ seed; }
Q_DECL_CONST_FUNCTION Q_DECL_CONSTEXPR inline uint qHash(short key, uint seed = 0) Q_DECL_NOTHROW { return uint(key) ^ seed; }
Q_DECL_CONST_FUNCTION Q_DECL_CONSTEXPR inline uint qHash(uint key, uint seed = 0) Q_DECL_NOTHROW { return key ^ seed; }
Q_DECL_CONST_FUNCTION Q_DECL_CONSTEXPR inline uint qHash(int key, uint seed = 0) Q_DECL_NOTHROW { return uint(key) ^ seed; }
Q_DECL_CONST_FUNCTION Q_DECL_CONSTEXPR inline uint qHash(ulong key, uint seed = 0) Q_DECL_NOTHROW{return (sizeof(ulong) > sizeof(uint))? (uint(((key >> (8 * sizeof(uint) - 1)) ^ key) & (~0U)) ^ seed) : (uint(key & (~0U)) ^ seed);}
Q_DECL_CONST_FUNCTION Q_DECL_CONSTEXPR inline uint qHash(long key, uint seed = 0) Q_DECL_NOTHROW { return qHash(ulong(key), seed); }
Q_DECL_CONST_FUNCTION Q_DECL_CONSTEXPR inline uint qHash(quint64 key, uint seed = 0) Q_DECL_NOTHROW{ return uint(((key >> (8 * sizeof(uint) - 1)) ^ key) & (~0U)) ^ seed;}
Q_DECL_CONST_FUNCTION Q_DECL_CONSTEXPR inline uint qHash(qint64 key, uint seed = 0) Q_DECL_NOTHROW { return qHash(quint64(key), seed); }
Q_CORE_EXPORT Q_DECL_CONST_FUNCTION uint qHash(float key, uint seed = 0) Q_DECL_NOTHROW;
Q_CORE_EXPORT Q_DECL_CONST_FUNCTION uint qHash(double key, uint seed = 0) Q_DECL_NOTHROW;
#ifndef Q_OS_DARWIN
Q_CORE_EXPORT Q_DECL_CONST_FUNCTION uint qHash(long double key, uint seed = 0) Q_DECL_NOTHROW;
#endif
Q_DECL_CONST_FUNCTION Q_DECL_CONSTEXPR inline uint qHash(const QChar key, uint seed = 0) Q_DECL_NOTHROW { return qHash(key.unicode(), seed); }
Q_CORE_EXPORT Q_DECL_PURE_FUNCTION uint qHash(const QByteArray &key, uint seed = 0) Q_DECL_NOTHROW;
Q_CORE_EXPORT Q_DECL_PURE_FUNCTION uint qHash(const QString &key, uint seed = 0) Q_DECL_NOTHROW;
Q_CORE_EXPORT Q_DECL_PURE_FUNCTION uint qHash(const QStringRef &key, uint seed = 0) Q_DECL_NOTHROW;
Q_CORE_EXPORT Q_DECL_PURE_FUNCTION uint qHash(const QBitArray &key, uint seed = 0) Q_DECL_NOTHROW;
Q_CORE_EXPORT Q_DECL_PURE_FUNCTION uint qHash(QLatin1String key, uint seed = 0) Q_DECL_NOTHROW;
Q_CORE_EXPORT Q_DECL_PURE_FUNCTION uint qt_hash(const QString &key) Q_DECL_NOTHROW;
Q_CORE_EXPORT Q_DECL_PURE_FUNCTION uint qt_hash(const QStringRef &key) Q_DECL_NOTHROW;template <class T> inline uint qHash(const T *key, uint seed = 0) Q_DECL_NOTHROW
{return qHash(reinterpret_cast<quintptr>(key), seed);
}
template<typename T> inline uint qHash(const T &t, uint seed)Q_DECL_NOEXCEPT_EXPR(noexcept(qHash(t)))
{ return (qHash(t) ^ seed); }template <typename T1, typename T2> inline uint qHash(const QPair<T1, T2> &key, uint seed = 0)Q_DECL_NOEXCEPT_EXPR(noexcept(qHash(key.first, seed)) && noexcept(qHash(key.second, seed)))
{uint h1 = qHash(key.first, seed);uint h2 = qHash(key.second, seed);return ((h1 << 16) | (h1 >> 16)) ^ h2 ^ seed;
}
qHash中關(guān)于處理指針鍵值的哈希函數(shù),如下:
Q_CORE_EXPORT Q_DECL_PURE_FUNCTION uint qHashBits(const void *p, size_t size, uint seed = 0) Q_DECL_NOTHROW;
template <class T> inline uint qHash(const T *key, uint seed = 0) Q_DECL_NOTHROW
{
??? return qHash(reinterpret_cast<quintptr>(key), seed);
}
指針哈希函數(shù)應(yīng)用如下:(其中handle為第三方庫(kù)智能指針,1、3例指針轉(zhuǎn)int可能會(huì)溢出)
?
inline uint qHash(const Handle(AIS_Shape)& key){return qHash(reinterpret_cast<quintptr>(key.get()));//return qHashBits(key.get(), sizeof(AIS_Shape*), 0);//return qHash((int)key.get());}
?6,Qt關(guān)聯(lián)容器和集合的算法復(fù)雜性:
?使用QVector,QHash和QSet,附加項(xiàng)的性能攤銷為O(log?n)。在插入項(xiàng)目之前,可以通過(guò)調(diào)用QVector :: reserve(),QHash :: reserve()(或QSet :: reserve()并使用預(yù)期的項(xiàng)目數(shù)將其降至O(1)。
原文鏈接:https://blog.csdn.net/qq_43405330/article/details/108028980
總結(jié)
以上是生活随笔為你收集整理的QT之QHash简介的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。