当找不到密钥时,了解QHash的作用 [英] Understanding what QHash does when key not found

查看:124
本文介绍了当找不到密钥时,了解QHash的作用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

注意:您可以在本文结尾处找到一个最小的工作示例.

Note: You can find a minimal working example at the end of this post.

我正在使用 Qt 5.7 .假设我有以下QHash:

I'm using Qt 5.7. Let's say I have the following QHash:

QHash<HashKey, HashValue> hm;

enum HashKey {
    K1,
    K2,
    K3,
    K4,
    K5
}

class HashValue {
    public:
        int x;
        HashValue(int x) {
            this->x = x;
        }
}

我已经像这样初始化了哈希图:

I have initialized the hash map like this:

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));

我已经通过致电进行了测试

I have tested it by calling

cout << hm.value(K4).x << endl;
cout << hm.find(K4).value().x << endl;

两者都返回与3相同的结果.现在,我尝试通过将整数转换为HashKey并在其上调用上述两个方法,来对不属于哈希映射的键进行相同的操作:

Both return the same result that is 3. Now I tried doing the same with a key that is not part of the hash map by casting an integer to HashKey and calling the above two methods on it:

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的呼叫)

What I got is 8 (for the first call with value().x) and 5 (for the second call with find(...).value().x)

文档指出

如果哈希中没有具有指定键的项目,则这些 函数返回默认构造值.

If there is no item with the specified key in the hash, these functions return a default-constructed value.

我点击了default-constructed value的链接,并得到了以下内容:

I followed the link for default-constructed value and got the following:

[...],例如,QVector使用以下命令自动初始化其项目 默认构造的值,并且QMap :: value()返回一个 如果指定的键不在地图中,则为默认构造的值.为了 大多数值类型,这仅表示使用 默认构造函数(例如,QString为空字符串).但对于 原始类型(例如int和double)以及指针类型, C ++语言不指定任何初始化.在这种情况下,Qt的 容器会自动将值初始化为0.

[...] for example, QVector automatically initializes its items with default-constructed values, and QMap::value() returns a default-constructed value if the specified key isn't in the map. For most value types, this simply means that a value is created using the default constructor (e.g. an empty string for QString). But for primitive types like int and double, as well as for pointer types, the C++ language doesn't specify any initialization; in those cases, Qt's containers automatically initialize the value to 0.

在我的情况下,这意味着要调用HashValue().但是,我得到不同结果的事实至少使人困惑.我希望得到相同的结果,尽管文档中没有提及将无效键作为参数传递时find(...)的作用.它说的所有内容都找到了该键的第一个匹配项,并返回了一个迭代器(显然是因为我在上面的调用中对它调用了value().)

In my case this would mean a HashValue() call. However the fact that I get different results is baffling to say the least. I would expect to get the same result though the docs don't mention what find(...) does when an invalid key is passed as argument. All it says it finds the first occurrence of that key and returns an iterator (obviously since I call value() on it in the call above).

如果要检查哈希是否包含特定键,请使用 contains()

If you want to check whether the hash contains a particular key, use contains()

我每次查询哈希映射时都必须调用contains(),尽管这意味着要进行两个函数调用-首先检查键是否存在,然后调用value(...)以获取有效值的实际值.找到条目.下面的调用返回"Key 100 not found":

I can deal with having to call contains() every time I query my hash map though this means making two function calls - first to check if key is present and then to call value(...) to get the actual value if a valid entry is found. The call below returns "Key 100 not found":

cout << (hm.contains(static_cast<HashKey>(100)) ? "Key 100 found" : "Key 100 not found") << endl;

我希望此检查在内部完成,但显然不会发生(我想是为了防止对该容器的查询功能造成一些性能影响).

I would expect this check to be done internally but obviously this doesn't happen (my guess would be to prevent some performance impact on the querying functionality of this container).

这里的问题是,为什么会发生所有这些事情,以及在这一切之下实际上发生了什么?

The question here is why is all this happening and what is actually happening underneath all that?

这是项目及其代码:

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();
}

推荐答案

value()函数基本上仅用于访问值,而不检查您是否有一个值.

The value() function is basically just for accessing values not checking if you have a one.

它返回一个值,并且无法指示该值是否为无效".因此,选择是否要设计一个.作为替代方案,Qt可能会引发异常,但是由于多种原因(与c ++标准库btw的容器相同),此处并未这样做.

It returns a value and there is no way to indicate whether the value is "invalid" or not. So the choice if the design was to construct one. Qt could as an alternative throw an exception but this is not done here for several reasons (same as the containers of the c++ standard library btw.).

第二:

您有点以错误的方式使用find().

You are kind of using find() in a wrong way.

使用find,您可以检查密钥是否在列表中,并且如果不是,则指向哈希的end()迭代器.

With find you can check whether the key is in the list and if not it point to the end() iterator of the hash.

QHash< Key,Value >::const_iterator valueIt = hash.find(<something>)
if(valueIt == hash.end())
{  // not found. error handling etc. 
}
Value value = valueIt.value();

这通常是检查密钥是否存在并在Map/Hash/Set/...中访问它的标准"方法.

This is usually the "standard" way to check if a key exists and access it in a Map/Hash/Set/....

因此,当您使用

find(...).value();

您可能会访问导致不确定行为的end()迭代器.

you could possibly access the end() iterator which causes undefined behavior.

这篇关于当找不到密钥时,了解QHash的作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆