std:map如何检查两个对象是否相等?

时间:2016-10-11 14:45:53

标签: c++ stdmap

为什么以下代码打印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会告诉您该项目是否已经在容器中。

1 个答案:

答案 0 :(得分:6)

地图insert()使用您提供的operator<来确定元素之间的等效性。如果a < bb < a都为false,则认为这两个元素相等。

您的operator<()不一致,因为它没有定义必要的strict weak ordering。例如,考虑a.bar < b.barb.baz < a.baz;然后a < b为false且b < a为false,因此地图相信a == b

在特定情况下,在比较firstsecond时,first.bazsecond.baz都是"test",因此两个比较都返回false,元素被认为是平等的。

您需要以下内容:

bool operator<(const Foo& rhs) const
{
    return std::tie(bar, baz) < std::tie(rhs.bar, rhs.baz);
}