c++ - 自定义类的 unordered_map 在插入相同的键时不会导致错误

标签 c++ unordered-map

我正在尝试找出使用 unordered_map 的一些要点用于自定义类。下面是我用来练习的代码,我定义了一个简单的类 Line .我很困惑为什么要插入 Line2main()不使程序输出 insert failedm 的值对于 Line1Line2都是3 .请注意,因为我只比较 m 中的第一个值(即 operator== )在 class Line 中发挥作用,因此 Line1Line2在此代码中应具有相同的 key 。插入一个已经存在的 key 不应该是无效的吗?有人可以向我解释为什么吗?谢谢!

#include<iostream>                                                                                                                                                                                                                                                                                                                                                                                                                                          
#include<unordered_map>                                                                                                                                                                                                                    

using namespace std;                                                                                                                                                                                                                       
class Line {                                                                                                                                                                                                                               
public:                                                                                                                                                                                                                                    
  float m;                                                                                                                                                                                                                                 
  float c;                                                                                                                                                                                                                                 

  Line() {m = 0; c = 0;}                                                                                                                                                                                                                   
  Line(float mInput, float cInput) {m = mInput; c = cInput;}                                                                                                                                                                               
  float getM() const {return m;}                                                                                                                                                                                                           
  float getC() const {return c;}                                                                                                                                                                                                           
  void setM(float mInput) {m = mInput;}                                                                                                                                                                                                    
  void setC(float cInput) {c = cInput;}                                                                                                                                                                                                    

  bool operator==(const Line &anotherLine) const                                                                                                                                                                                           
    {                                                                                                                                                                                                                                      
      return (m == anotherLine.m);                                                                                                                                                                                                         
    }                                                                                                                                                                                                                                      
};                                                                                                                                                                                                                                         

namespace std                                                                                                                                                                                                                              
{                                                                                                                                                                                                                                          
  template <>                                                                                                                                                                                                                              
  struct hash<Line>                                                                                                                                                                                                                        
  {                                                                                                                                                                                                                                        
    size_t operator()(const Line& k) const                                                                                                                                                                                                 
      {                                                                                                                                                                                                                                    
        // Compute individual hash values for two data members and combine them using XOR and bit shifting                                                                                                                                 
        return ((hash<float>()(k.getM()) ^ (hash<float>()(k.getC()) << 1)) >> 1);                                                                                                                                                          
      }                                                                                                                                                                                                                                    
  };                                                                                                                                                                                                                                       
}                                                                                                                                                                                                                                          

int main()                                                                                                                                                                                                                                 
{                                                                                                                                                                                                                                          
  unordered_map<Line, int> t;                                                                                                                                                                                                              

  Line line1 = Line(3.0,4.0);                                                                                                                                                                                                              
  Line line2 = Line(3.0,5.0);                                                                                                                                                                                                              

  t.insert({line1, 1});                                                                                                                                                                                                                                                                                                                                                                                                                                      
  auto x = t.insert({line2, 2});                                                                                                                                                                                                           
  if (x.second == false)                                                                                                                                                                                                                   
    cout << "insert failed" << endl;                                                                                                                                                                                                       

  for(unordered_map<Line, int>::const_iterator it = t.begin(); it != t.end(); it++)                                                                                                                                                        
  {                                                                                                                                                                                                                                        
    Line t = it->first;                                                                                                                                                                                                                    
    cout << t.m << " " << t.c << "\n" ;                                                                                                                                                                                                    
  }                                                                                                                                                                                                                                        

  return 1;                                                                                                                                                                                                                                
}    

最佳答案

您的 hashoperator == 必须满足它们当前违反的一致性要求。根据==,当两个对象相等时,根据hash,它们的哈希码必须相等。换句话说,虽然不相等的对象可能具有相同的哈希码,但相等的对象必须具有相同的哈希码:

size_t operator()(const Line& k) const  {
    return hash<float>()(k.getM());
}   

由于您只比较一个组件的相等性,而忽略另一个组件,因此您需要更改哈希函数以使用您用来确定相等性的相同组件。

关于c++ - 自定义类的 unordered_map 在插入相同的键时不会导致错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47376585/

相关文章:

c++ - 标准要求 std::unordered_map 将键值对放在内存中吗?

c++ - 更新 Directx 10 和 11 中的顶点缓冲区

c++ - 使用Eclipse运行C代码的.exe文件

c++ - 旋转纹理openGL C++

引用 vector 中的 unordered_map 时出现 C++11 段错误

c++ - unordered_map 值对 C++

C++排序算法

c++ - 将现有的 C++ 对象传递给 Lua

c++ - 析构函数、图和递归

c++ - emplace 和 unordered_map<?, std::array<?, N>>