std:map 如何检查两个对象是否相等?
How does std:map check whether two objects are equal?
即使我在地图中插入了两个元素,为什么以下代码会打印 1
?
#include <iostream>
#include <map>
#include <string>
#include <utility>
struct Foo
{
Foo(int bar, const std::string& baz)
: bar(bar)
, baz(baz)
{}
int bar;
std::string baz;
bool operator<(const Foo& rhs) const
{
if (bar < rhs.bar && baz < rhs.baz)
{
return true;
}
else
{
return false;
}
}
};
int main()
{
Foo first(0, "test");
Foo second(1, "test");
std::map<Foo, std::string> m;
m.insert(std::make_pair(first, "test"));
m.insert(std::make_pair(second, "test1"));
std::cout << m.size() << std::endl;
}
第二次调用 insert()
表示我们已经在地图中找到了该项目。为什么?
我的previous question因为打字错误被错误关闭了。我知道 insert
会告诉您该物品是否已经在容器中。
地图的 insert()
使用您提供的 operator<
来决定元素之间的等价性。如果 a < b
和 b < a
都为假,则认为这两个元素相等。
您的 operator<()
不一致,因为它没有定义必要的 strict weak ordering。例如,考虑 a.bar < b.bar
和 b.baz < a.baz
;那么 a < b
是假的,b < a
是假的,所以地图相信 a == b
.
在你的具体情况下,当比较first
和second
时,first.baz
和second.baz
都是"test"
,所以两个比较return false,元素被认为是相等的。
你需要这样的东西:
bool operator<(const Foo& rhs) const
{
return std::tie(bar, baz) < std::tie(rhs.bar, rhs.baz);
}
即使我在地图中插入了两个元素,为什么以下代码会打印 1
?
#include <iostream>
#include <map>
#include <string>
#include <utility>
struct Foo
{
Foo(int bar, const std::string& baz)
: bar(bar)
, baz(baz)
{}
int bar;
std::string baz;
bool operator<(const Foo& rhs) const
{
if (bar < rhs.bar && baz < rhs.baz)
{
return true;
}
else
{
return false;
}
}
};
int main()
{
Foo first(0, "test");
Foo second(1, "test");
std::map<Foo, std::string> m;
m.insert(std::make_pair(first, "test"));
m.insert(std::make_pair(second, "test1"));
std::cout << m.size() << std::endl;
}
第二次调用 insert()
表示我们已经在地图中找到了该项目。为什么?
我的previous question因为打字错误被错误关闭了。我知道 insert
会告诉您该物品是否已经在容器中。
地图的 insert()
使用您提供的 operator<
来决定元素之间的等价性。如果 a < b
和 b < a
都为假,则认为这两个元素相等。
您的 operator<()
不一致,因为它没有定义必要的 strict weak ordering。例如,考虑 a.bar < b.bar
和 b.baz < a.baz
;那么 a < b
是假的,b < a
是假的,所以地图相信 a == b
.
在你的具体情况下,当比较first
和second
时,first.baz
和second.baz
都是"test"
,所以两个比较return false,元素被认为是相等的。
你需要这样的东西:
bool operator<(const Foo& rhs) const
{
return std::tie(bar, baz) < std::tie(rhs.bar, rhs.baz);
}