注意:您可以在本文末尾找到最小的工作示例。
我使用 Qt 5.7 。我们说我有以下QHash
:
QHash<HashKey, HashValue> hm;
带
enum HashKey {
K1,
K2,
K3,
K4,
K5
}
和
class HashValue {
public:
int x;
HashValue(int x) {
this->x = x;
}
}
我已经像这样初始化了哈希映射:
hm.insert(K1, HashValue((int)K1));
hm.insert(K2, HashValue((int)K2));
hm.insert(K3, HashValue((int)K3));
hm.insert(K4, HashValue((int)K4));
hm.insert(K5, HashValue((int)K5));
我通过调用
测试了它cout << hm.value(K4).x << endl;
cout << hm.find(K4).value().x << endl;
两者都返回3
的相同结果。现在我尝试使用不是哈希映射的一部分的键,通过将一个整数转换为HashKey
并在其上调用上述两个方法来做同样的事情:
cout << hm.value(static_cast<HashKey>(100)).x << endl;
cout << hm.find(static_cast<HashKey>(100)).value().x << endl;
我得到的是8
(对于value().x
的第一次通话)和5
(对于find(...).value().x
的第二次通话)
文档说明
如果散列中没有指定键的项目,则为: 函数返回default-constructed value。
我按照default-constructed value
的链接获得了以下内容:
例如,[...],QVector会自动初始化其项目 默认构造的值,QMap :: value()返回一个 如果指定的键不在地图中,则为default-construct值。对于 大多数值类型,这只是意味着使用。创建一个值 默认构造函数(例如,QString的空字符串)。但对于 原始类型,如int和double,以及指针类型, C ++语言没有指定任何初始化;在那些情况下,Qt's 容器自动将值初始化为0。
在我的情况下,这意味着HashValue()
电话。然而,我得到不同结果的事实至少可以说是令人费解。我希望得到相同的结果,虽然文档没有提到当无效密钥作为参数传递时find(...)
做什么。所有它说它找到第一次出现的那个键并返回一个迭代器(显然,因为我在上面的调用中调用了value()
)。
通过上面引用的文档片段(再次回到QHash
的文档)
如果要检查哈希是否包含特定键,请使用 含有()
我可以处理每次查询哈希映射时都必须调用contains()
这虽然这意味着进行两次函数调用 - 首先检查密钥是否存在然后调用value(...)
来获取实际值如果找到有效条目,则为value。以下调用返回"Key 100 not found"
:
cout << (hm.contains(static_cast<HashKey>(100)) ? "Key 100 found" : "Key 100 not found") << endl;
我希望这项检查在内部完成,但显然这不会发生(我的猜测是防止对此容器的查询功能产生一些性能影响)。
这里的问题是为什么所有这一切都发生了,而实际发生的是什么?
这是项目及其代码:
HashTest.pro
QT += core
QT += gui
CONFIG += c++11
TARGET = HashTest
CONFIG += console
CONFIG -= app_bundle
TEMPLATE = app
SOURCES += main.cpp
的main.cpp
#include <QCoreApplication>
#include <QHash>
#include <iostream>
using namespace std;
enum HashKey {
K1 = 0,
K2 = 1,
K3 = 2,
K4 = 3,
K5 = 4
};
class HashValue {
public:
int x;
HashValue(int x) { this->x = x; }
HashValue() {}
};
int main(int argc, char *argv[])
{
QHash<HashKey, HashValue> hm;
hm.insert(K1, HashValue((int)K1));
hm.insert(K2, HashValue((int)K2));
hm.insert(K3, HashValue((int)K3));
hm.insert(K4, HashValue((int)K4));
hm.insert(K5, HashValue((int)K5));
cout << hm.value(K4).x << endl;
cout << hm.value(static_cast<HashKey>(100)).x << endl;
cout << hm.find(K4).value().x << endl;
cout << hm.find(static_cast<HashKey>(100)).value().x << endl;
cout << (hm.contains(static_cast<HashKey>(100)) ? "Key 100 found" : "Key 100 not found") << endl;
return a.exec();
}
答案 0 :(得分:6)
value()
函数基本上只是用于访问值,而不是检查是否有一个值。
它返回一个值,并且无法指示该值是否为&#34;无效&#34;或不。所以选择设计是否构建一个。 Qt可以作为一个替代方案抛出异常,但由于几个原因(这与c ++标准库btw的容器相同),这里没有这样做。)
其次:
您正在以错误的方式使用find()
。
使用find
,您可以检查密钥是否在列表中,如果不是,则指向散列的end()
迭代器。
QHash< Key,Value >::const_iterator valueIt = hash.find(<something>)
if(valueIt == hash.end())
{ // not found. error handling etc.
}
Value value = valueIt.value();
这通常是&#34;标准&#34;检查密钥是否存在的方法,并在Map / Hash / Set / ....
中访问它所以当你使用
时find(...).value();
您可能会访问导致未定义行为的end()
迭代器。