标准::设置运算符的使用<

std::set use of operator<

本文关键字:lt 设置 运算符 标准      更新时间:2023-10-16

这个问题与我在这里的另一个问题有点相关:链接(请参阅评论中的讨论)。基本上,我有以下问题:

我有一节课node。它有一些字段,最重要的是:GHpos(pos是Qt的QPoint,但为了示例起见,我已经将其重写为我自己的类Point。参见下面的示例:

#include <algorithm>
#include <iostream>
#include <memory>
#include <set>
class Point
{
public:
int _x, _y;
Point() : _x(0), _y(0) {}
Point(int x, int y) : _x(x), _y(y) {}
bool operator==(const Point& p) const { return _x == p._x && _y == p._y; }
bool operator!=(const Point& p) const { return _x != p._x && _y != p._y; }
};
class node
{
public:
node() {}
node(const Point& p) : pos(p) {}
bool operator==(const node& o) const { return pos == o.pos; }
bool operator==(const Point& o) const { return pos == o; }
bool operator!=(const node& o) const { return pos != o.pos; }
bool operator<(const node& o) const { return G + H < o.G + o.H; }
Point pos;
std::shared_ptr<node> parent;
int G = 0;
int H = 0;
};
int main()
{
node n1(Point(6, 7));
n1.G = 1;
n1.H = 1;
node n2(Point(1, 1));
n2.G = 2;
n2.H = 2;
node n3(Point(2, 2));
n3.G = 1;
n3.H = 1;
std::set<node> nodes;
nodes.insert(n1);
nodes.insert(n2);
nodes.insert(n3);
auto min = (*std::min_element(nodes.begin(), nodes.end())).pos;
std::cout << min._x << " " << min._y << 'n';
std::cout << nodes.size() << 'n';
}

该程序的输出为:

>main.exe
6 7
2

因此,搜索最低元素是成功的(使用operator<)。所以这就是我想要的。但正如您所看到的,我创建的三个node具有不同的.pos字段(基本上是坐标)。所以我希望他们所有人都能在一套中出席。换句话说,你可以说每个节点的"唯一性"应该由.pos字段来确定(实际上使用这个字段的operator==,我在上面定义了它)。其中一个节点被认为不是唯一的,因为std::set使用operator<来比较其元素。因此,n1n3具有相同的G+H值,并且它们被认为相等(输出的第二行中的2是集合元素的数量->2,而不是3)。

在我知道std::set使用operator<来比较相等之前,我已经编写了operator==operator!=,认为集合将使用其中一个来比较我类的对象。但它使用CCD_ 23。

所以我的问题是为什么它实际上使用这个运算符。使用operator==operator!=不是更容易吗?

对我来说,这有点复杂,因为我必须想另一种方法来写operator<或使用不同的容器(因此写lambdas),或者我可以在operator<中使用.pos进行比较,然后自己重写std::min_element(在帐户中取GH的和,而不是.pos字段)

您试图实现的内容违反了std::set的严格弱序要求。基本上,如果你有两个数字,并且两者都不小于另一个,那么它们一定是相同的!它们也不能不同(当使用一些不同的语法进行检查时)。

应该一致地定义所有的比较运算符,这样就可以清楚地了解类型的。您类型的哪些成员显著,即对价值有贡献?可能还有其他成员,但不应在比较运算符中检查它们。

例如std::vector。如果两个vector都包含a, b, c,则它们相等。它们可能有不同数量的未使用存储空间(vector.capacity()),但这不是任一对象的一部分。

如果你有时间的话,约翰·拉科斯已经介绍了这一点,亚历山大·斯捷潘诺夫也写过这一点