【问题标题】:Strange behavior of the std::map with atypical comparator带有非典型比较器的 std::map 的奇怪行为
【发布时间】:2014-10-13 20:37:56
【问题描述】:

让我们考虑以下代码 sn-p:

class A 
{
    public:
    int x;
    int y;
    A(int ix, int iy) : x(ix), y(iy) {}
    bool operator < (const A& a) const
    { return (x < a.x) || (y < a.y); } 
};


int main()
{
    std::map<A,int> amap;
    amap[A(0,1)] = 4;
    amap[A(1,0)] = 5;
    for(auto &x: amap)
        std::cout<<x.second<<std::endl;
    std::cout<<amap[A(0,1)]<<std::endl;
    std::cout<<amap[A(1,0)]<<std::endl;
}

输出为5 4 4 0

  • 我预计只会插入第一个元素A(0,1),但添加了两个元素。为什么?
  • 已找到第一个元素A(0,1),但第二次搜索元素A(1,0) 未找到。为什么?

有人可以在std::map 中详细解释这种情况下发生的情况吗?

【问题讨论】:

  • 您的比较运算符没有实现严格的弱排序。这是一个要求,所以你的地图坏了。
  • @ juanchopanza,我明白了,但是……为什么会有这种行为?
  • std::map 的内部结构需要这个。它是一个二叉搜索树。
  • @gorill - 使用 Visual Studio,您会收到使用调试库的断言,因此不会看到“行为”。 VS 使用两次调用比较器的技巧,一次使用参数“a,b”,然后使用“b,a”进行比较器。如果您同时返回true,则会显示断言。

标签: c++ stl stdmap


【解决方案1】:
A a(0, 1), b(1, 0);

然后a &lt; b &amp;&amp; b &lt; a。如您所见,您的排序不是不对称的。也不是像a &lt; a 那样不自反。 所有这些都是严格弱排序的要求,每个map 需要排序。没有它,您的结果很快就会变得不可预测。

【讨论】:

    【解决方案2】:

    对于您插入到地图中的所有元素,如果a &lt; b 为真,那么b &lt; a 必须为假。您的比较运算符不会这样做。

    map 使用树结构,并使用比较运算符完成树的导航。如果比较运算符生成不一致的结果,则导航会丢失。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-08
      • 2014-08-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多