unordered_set示例编译器错误(可能是哈希和等价函数错误)

时间:2014-08-11 19:37:30

标签: c++ c++11 hash c++-standard-library unordered-set

我试图在C ++ 11中编译这段代码,它给了我编译错误:

#include <iostream> 
#include <unordered_set>

using namespace std; 

class Point{
  int x,y; 
 public: 
  Point(int a=0, int b=0): x(a), y(b) {}; 
  int getX(void){ return x;} 
  int getY(void){ return y;} 
};


class monkeyHash{
 public: 
    size_t operator()(const Point & xy){
        size_t h1 = std::hash<int>()(xy.getX()); 
        size_t h2 = std::hash<int>()(xy.getY());
        return (h1 ^ (h2<<1));  
 }
};

struct monkeyEquals{
 bool operator()(const Point & lhs, const Point & rhs){
     return (lhs.getX() == rhs.getX()) && (lhs.getY() == rhs.getY()); 
 }
};

int main(){
  unordered_set<Point,monkeyHash,monkeyEquals> visited; 
  visited.insert(Point(0,0));   

}

我得到的错误消息很长,所以我将总结一下:

In member function ‘size_t monkeyHash::operator()(const Point&)’:
monkey.cpp:26:50: error: passing ‘const Point’ as ‘this’ argument of ‘int    Point::getX()’ discards qualifiers [-fpermissive]
monkey.cpp:27:50: error: passing ‘const Point’ as ‘this’ argument of ‘int Point::getY()’ discards qualifiers [-fpermissive]
monkey.cpp: In member function ‘bool monkeyEquals::operator()(const Point&, const Point&)’:

它似乎也抱怨我的哈希函数。我的哈希方式是不正确的? 我仍然是模板,c ++ 11和STL的新手,很抱歉,如果这个问题很无聊。

1 个答案:

答案 0 :(得分:1)

声明那些方法const

int getX(void) const { return x; }
int getY(void) const { return y; }

像这样使用const告诉编译器该方法不会更改类实例。只有这样你才能在const Point对象上调用它。

在C ++ 11中,你可能还想标记它们noexcept,(例如int getX() const noexcept { return x; },因为它们不会抛出任何异常。如果你标记它们noexcept,编译器可能会更多地优化您的代码。

size_t monkeyHash::operator()(const Point &)bool monkeyEquals::operator()(const Point &, const Point &)方法也是如此。

PS:如果您在monkeyEquals中重载operator==,则可以摆脱class Point {}课程:

inline bool operator==(const Point & rhs) const noexcept
{ return (x == rhs.x) && (y == rhs.y); }

您还可以覆盖operator!=

inline bool operator!=(const Point & rhs) const noexcept
{ return (x != rhs.x) || (y != rhs.y); }

请参阅this wikipedia article,了解如何在命名空间std中编写更好的自定义哈希函数。

如果您接受此post-scriptum中的建议,您可以像这样声明容器:

unordered_set<Point> visited;