好吧,经过四个小时的调试,我很困惑,我发现了问题的原因......
我正在制作一些程序,可以在std :: map中保存一些点并在窗口中渲染它们。 但奇怪的是,有些观点未能将其纳入地图。
std::map<Point2, Prop*> m_Props_m;
void AddProp(std::pair<Point2, Prop*> p)
{
m_Props_m.insert(p);
}
struct Point2
{
unsigned int Point2::x;
unsigned int Point2::y;
//--------
Point2::Point2()
:x(0)
,y(0)
{}
bool Point2::operator< (const Point2& b) const
{
return ( x+y < b.x+b.y );
}
bool Point2::operator> (const Point2& b) const
{
return ( x+y > b.x+b.y );
}
};
感谢上帝,我对二叉树有一些经验,所以我可以找出问题的原因。
想象一下,我们有2个Point2。
Point2 a(0,1);
Point2 b(1,0);
如您所见,运营商&lt;方法我写的它会返回false,而运算符&gt;也会返回假。因此,如果a已经在地图中,并且插入了b,则插入失败。
现在,这一切都很好,但我该如何解决这个问题呢?有没有什么方法可以为2D点设置一个小于操作符,以便我可以在地图中存储每个唯一的点?
答案 0 :(得分:11)
std::map
根本不使用operator>
,因此您不必担心这一点。
要对多个字段(在本例中为两个字段)进行排序,请使用所谓的&#34;字典排序&#34;,这意味着第一个字段最重要,第二个字段断开关系:
bool operator<(const Point2 &lhs, const Point2 &rhs) {
return (lhs.x < rhs.x) || ((lhs.x == rhs.x) && (lhs.y < rhs.y));
}
答案 1 :(得分:2)
如果坐标之和相等,则您的比较函数会考虑等效点。例如,(2,5)相当于(3,4),因为2 + 5 = 3 + 4.在地图中已经具有等价物的点将不会成功。
更好的想法是首先比较x,如果两个点的x值相等,则按y秒。
bool operator< (const Point2 &lhs, const Point2 &rhs) {
return (lhs.x < rhs.x) || ((lhs.x == rhs.x) && (lhs.y < rhs.y));
}
答案 2 :(得分:1)
这应该可以解决问题:
bool Point2::operator< (const Point2& b) const
{
if (x<b.x) return true;
else if (!(b.x<x) && y<b.y) return true;
else return false;
}
std::map
仅使用operator<
。如果!(a<b) && !(b<a)
,a
和b
相等(不相同),则地图只会存储其中一个。 <{1}}未使用。
在其他情况下比较Point2可能没有意义,所以为了避免误解,我建议您为地图提供比较功能,并从班级中删除operator>
。
operator<
在我看来,操作符重载只应在对给定类型有意义时使用,并且2D空间中的一个点大于2D空间中的另一个点是不直观的。