2016-10-11 11 views
2

注:この記事の末尾には、最小限の作業例があります。キーが見つからないときのQHashの理解

私は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です。私が得たもの

cout << hm.value(static_cast<HashKey>(100)).x << endl; 
cout << hm.find(static_cast<HashKey>(100)).value().x << endl; 

8である(との最初の呼び出しのために:今、私はHashKeyの整数をキャストし、その上に上記の2つのメソッドを呼び出すことにより、ハッシュマップの一部ではないキーと同じことをやってみましたハッシュ内の指定されたキーにない項目、これら 関数RETがない場合value().x)と5は()find(...).value().xと第2の呼のための

ドキュメントその

を述べurn a default-constructed value

私はdefault-constructed valueのリンクをたどって、以下を得た:

)[...]例えば、QVectorが自動的 デフォルト-構築した値でその項目を初期化し、QMap ::値(指定されたキーがマップにない場合は、 デフォルト構築値を返します。ほとんどの値タイプが の場合、これは単に デフォルトコンストラクタ(たとえばQStringの空の文字列)を使用して値が作成されたことを意味します。しかし、 のintやdoubleやポインタ型のプリミティブ型の場合、 C++言語は初期化を指定しません。これらの例では、Qtの コンテナは自動的に、これはHashValue()コールを意味するであろう私の場合

値を0に初期化します。しかし、私が違う結果を出すという事実は、あまり言い表せないのです。無効なキーが引数として渡されたときに、find(...)が何を言及していないとしても、私は同じ結果を得ることを期待しています。すべてそれは、そのキーの最初の出現を見つけ出し、イテレータを返すと言います(私が上記の呼び出しでそれにvalue()を呼び出すので、明らかに)。

あなたは、ハッシュは、特定のキーが含まれているかどうかをチェック

)( が含まれている使用したい場合は、上から引用されたドキュメントスニペットは(再び QHashのための文書へ)

が続いています

私はハッシュマップをクエリするたびにを呼び出す必要があります。これは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(); 
} 

答えて

6

value()機能だけでアクセスするための基本的です値がある場合はチェックしません。

値を返し、値が「無効」かどうかを示す方法はありません。だから設計が1つを構成するかどうか。 Qtは例外として例外をスローすることができますが、これはいくつかの理由からここでは行われません(C++標準ライブラリbtwのコンテナと同じです)。第二に

あなたは間違った方法でfind()を使用しての一種です。あなたがいない、それはハッシュのend()イテレータを指している場合、キーがリストにあるとかどうかを確認することができますfind

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

これは通常、「標準」キーが存在するかどうかを確認するための方法およびアクセス、それをあるマップ/ハッシュ/セット/ ....で

ですから、

find(...).value(); 
を使用する場合

end()イテレータにアクセスすると、未定義の動作が発生する可能性があります。

+0

詳細な回答ありがとうございます。^_ ^私は私が得ていた異なった値のために未定義の振る舞いを考えました、そして、私はそれが本当に事実だったと思います。ですから、あなたが示した方法で 'contains()'や 'find()'を使います。 – rbaleksandar

+1

@rbaleksandar値を使用したい場合はfindを使います。これで、一度「参照」するだけで済みます。 'contains'と' value'(またはfind)を使うと、2つのルックアップがあります。 – Hayt

+0

これは私が恐れていたものでした。さて、それはfind()です。 :) – rbaleksandar

関連する問題