标准::设置运算符的使用<
std::set use of operator<
这个问题与我在这里的另一个问题有点相关:链接(请参阅评论中的讨论)。基本上,我有以下问题:
我有一节课node
。它有一些字段,最重要的是:G
、H
和pos
(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<
来比较其元素。因此,n1
和n3
具有相同的G+H
值,并且它们被认为相等(输出的第二行中的2
是集合元素的数量->2,而不是3)。
在我知道std::set
使用operator<
来比较相等之前,我已经编写了operator==
和operator!=
,认为集合将使用其中一个来比较我类的对象。但它使用CCD_ 23。
所以我的问题是为什么它实际上使用这个运算符。使用operator==
或operator!=
不是更容易吗?
对我来说,这有点复杂,因为我必须想另一种方法来写operator<
或使用不同的容器(因此写lambdas),或者我可以在operator<
中使用.pos
进行比较,然后自己重写std::min_element
(在帐户中取G
和H
的和,而不是.pos
字段)
您试图实现的内容违反了std::set
的严格弱序要求。基本上,如果你有两个数字,并且两者都不小于另一个,那么它们一定是相同的!它们也不能不同(当使用一些不同的语法进行检查时)。
应该一致地定义所有的比较运算符,这样就可以清楚地了解类型的值。您类型的哪些成员显著,即对价值有贡献?可能还有其他成员,但不应在比较运算符中检查它们。
例如std::vector
。如果两个vector
都包含a, b, c
,则它们相等。它们可能有不同数量的未使用存储空间(vector.capacity()
),但这不是任一对象值的一部分。
如果你有时间的话,约翰·拉科斯已经介绍了这一点,亚历山大·斯捷潘诺夫也写过这一点
- 为不同配置设置MSVC_RUNTIME_LIBRARY的正确方法是什么
- 在C++/Linux中设置单调时钟的一些技巧
- 如何在选项卡视图Qt中设置一个新项目,并保存以前的项目
- 嵌套在类中时无法设置成员数据
- 需要帮助设置在C++中使用的Potrace
- 请解释这句话(cout<<1+int((a<b)^((b-a)&1) )<<endl
- 如何在自删除后将对象设置为nullptr
- 呼叫运营商<<临时
- 将指针设置为"nullptr"并不能防止双重删除?
- 如何在Ubuntu中使用cmake设置qt4
- ld:bind_at_load和-bitcode_bundle(Xcode设置ENABLE_bitcode=YES)不能
- 如何在boost beast http请求中设置http头
- 如何解决gcc编译器优化导致的centos双编译器设置中的分段错误
- 如何将这个C++哈希表转换为动态扩展和收缩,而不是使用硬设置的最大值
- 为什么文件名被设置为一个点,而不是在读取矢量中的文件名时
- 如何在24位SDL_Surface上设置像素的颜色
- std::设置自定义比较器
- 如何防止clang格式在流运算符调用之间添加换行符<<
- C++是否可以将fstream对象设置为在每次调用<<
- std::pair的默认构造函数<>将基本类型(int等)设置为零