注:この投稿の最後に、最小限の作業例があります。
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
ここで、整数をキャストして上記の2つのメソッドを呼び出すことにより、ハッシュマップの一部ではないキーで同じことを試みました。
cout << hm.value(static_cast<HashKey>(100)).x << endl;
cout << hm.find(static_cast<HashKey>(100)).value().x << endl;
私が得たのは8
( を使用した最初の呼び出しの場合value().x
) と5
( を使用した 2 番目の呼び出しの場合find(...).value().x
)です。
ドキュメントには次のように記載されています
ハッシュに指定されたキーを持つアイテムがない場合、これらの関数はデフォルトで構築された値を返します。
のリンクをたどったdefault-constructed value
ところ、次のものが得られました。
[...] たとえば、QVector はそのアイテムをデフォルトで構築された値で自動的に初期化し、指定されたキーがマップにない場合、QMap::value() はデフォルトで構築された値を返します。ほとんどの値の型では、これは値がデフォルトのコンストラクタ (QString の空の文字列など) を使用して作成されることを意味します。ただし、int や double などのプリミティブ型、およびポインター型の場合、C++ 言語は初期化を指定しません。そのような場合、Qt のコンテナーは自動的に値を 0 に初期化します。
私の場合、これはHashValue()
呼び出しを意味します。しかし、私が異なる結果を得たという事実は、控えめに言っても困惑しています。find(...)
ドキュメントには、無効なキーが引数として渡された場合の動作については言及されていませんが、同じ結果が得られると予想されます。そのキーの最初の出現を見つけてイテレータを返すと言っているだけです(明らかに、value()
上記の呼び出しでそれを呼び出しているためです)。
上から引用したドキュメント スニペットの後に (再び のドキュメントに戻るQHash
)、
ハッシュに特定のキーが含まれているかどうかを確認するには、contains() を使用します。
contains()
ハッシュマップをクエリするたびに呼び出す必要があることに対処できますが、これは 2 つの関数呼び出しを行うことを意味します。最初にキーが存在するかどうかを確認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();
}