title: Understanding what QHash does when key not found
body: <p><strong>Note:</strong> You can find a minimal working example at the end of this post.</p>
  
  <p>I'm using <strong>Qt 5.7</strong>. Let's say I have the following <code>QHash</code>:</p>
  
  <pre><code>QHash&lt;HashKey, HashValue&gt; hm;
  </code></pre>
  
  <p>with </p>
  
  <pre><code>enum HashKey {
      K1,
      K2,
      K3,
      K4,
      K5
  }
  </code></pre>
  
  <p>and</p>
  
  <pre><code>class HashValue {
      public:
          int x;
          HashValue(int x) {
              this-&gt;x = x;
          }
  }
  </code></pre>
  
  <p>I have initialized the hash map like this:</p>
  
  <pre><code>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));
  </code></pre>
  
  <p>I have tested it by calling</p>
  
  <pre><code>cout &lt;&lt; hm.value(K4).x &lt;&lt; endl;
  cout &lt;&lt; hm.find(K4).value().x &lt;&lt; endl;
  </code></pre>
  
  <p>Both return the same result that is <code>3</code>. Now I tried doing the same with a key that is not part of the hash map by casting an integer to <code>HashKey</code> and calling the above two methods on it:</p>
  
  <pre><code>cout &lt;&lt; hm.value(static_cast&lt;HashKey&gt;(100)).x &lt;&lt; endl;
  cout &lt;&lt; hm.find(static_cast&lt;HashKey&gt;(100)).value().x &lt;&lt; endl;
  </code></pre>
  
  <p>What I got is <code>8</code> (for the first call with <code>value().x</code>) and <code>5</code> (for the second call with <code>find(...).value().x</code>)</p>
  
  <p>The docs states that </p>
  
  <blockquote>
    <p>If there is no item with the specified key in the hash, these
    functions return a <a href="http://doc.qt.io/qt-5/containers.html#default-constructed-value" rel="nofollow">default-constructed value</a>.</p>
  </blockquote>
  
  <p>I followed the link for <code>default-constructed value</code> and got the following:</p>
  
  <blockquote>
    <p>[...] 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.</p>
  </blockquote>
  
  <p>In my case this would mean a <code>HashValue()</code> 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 <code>find(...)</code> 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 <code>value()</code> on it in the call above).</p>
  
  <p>The quoted doc snippet from above is followed (again back to the document for <code>QHash</code>) by </p>
  
  <blockquote>
    <p>If you want to check whether the hash contains a particular key, use
    contains()</p>
  </blockquote>
  
  <p>I can deal with having to call <code>contains()</code> 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 <code>value(...)</code> to get the actual value if a valid entry is found. The call below returns <code>"Key 100 not found"</code>:</p>
  
  <pre><code>cout &lt;&lt; (hm.contains(static_cast&lt;HashKey&gt;(100)) ? "Key 100 found" : "Key 100 not found") &lt;&lt; endl;
  </code></pre>
  
  <p>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).</p>
  
  <p>The question here is why is all this happening and what is actually happening underneath all that?</p>
  
  <p>Here is the project and the code for it:</p>
  
  <p><strong>HashTest.pro</strong></p>
  
  <pre><code>QT += core
  QT += gui
  
  CONFIG += c++11
  
  TARGET = HashTest
  CONFIG += console
  CONFIG -= app_bundle
  
  TEMPLATE = app
  
  SOURCES += main.cpp
  </code></pre>
  
  <p><strong>main.cpp</strong></p>
  
  <pre><code>#include &lt;QCoreApplication&gt;
  #include &lt;QHash&gt;
  #include &lt;iostream&gt;
  using namespace std;
  
  enum HashKey {
      K1 = 0,
      K2 = 1,
      K3 = 2,
      K4 = 3,
      K5 = 4
  };
  
  class HashValue {
  public:
      int x;
      HashValue(int x) { this-&gt;x = x; }
      HashValue() {}
  };
  
  int main(int argc, char *argv[])
  {
  
      QHash&lt;HashKey, HashValue&gt; 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 &lt;&lt; hm.value(K4).x &lt;&lt; endl;
      cout &lt;&lt; hm.value(static_cast&lt;HashKey&gt;(100)).x &lt;&lt; endl;
      cout &lt;&lt; hm.find(K4).value().x &lt;&lt; endl;
      cout &lt;&lt; hm.find(static_cast&lt;HashKey&gt;(100)).value().x &lt;&lt; endl;
      cout &lt;&lt; (hm.contains(static_cast&lt;HashKey&gt;(100)) ? "Key 100 found" : "Key 100 not found") &lt;&lt; endl;
  
      return a.exec();
  }
  </code></pre>