【问题标题】:C++ invalid comparatorC++ 无效比较器
【发布时间】:2017-05-31 07:13:21
【问题描述】:

我有一个奇怪的问题,也许我遗漏了一些明显的东西,但我无法弄清楚。

这是引发断言的 C++ 代码:

int compareByX(const Vector2D &a, const Vector2D &b)
{
    if (a.x < b.x) // if i put a.x > b.x nothing changes
        return -1;
    return 1;
}
int main(int argc, char *argv[])
{
    double pts[6] = { 5, 34, 3, 54, 10, 34 };
    std::vector<Vector2D> points;
    for (int i = 0; i < 6; i += 2)
        points.push_back({ pts[i],pts[i + 1] });
    std::sort(points.begin(), points.end(), compareByX);
}

发生的情况是第一点 (3, 54) 与 (5, 34) 进行测试,然后反之亦然。 此时会抛出断言(无效的比较器)。但我认为它有权返回 -1,因为 3 小于 5,然后返回 1,因为 5 大于 3...

你能告诉我这有什么问题吗?

【问题讨论】:

  • sort 期望比较函数返回 true (1) 或 false (0)。你认为-1 会发生什么?这种实现compareByX:{ return a.x &lt; b.x; }的方式怎么样?
  • This std::sort reference 应该会有所帮助。
  • 现在我明白了,谢谢!以为我正在使用 qsort :/
  • 对于 qsort,你仍然需要在相等时返回 0。
  • 是的,但我首先从: double diff =a.x-b.x ;返回(双(0)

标签: c++ sorting vector


【解决方案1】:

由于函数返回 -1 和 1,所以抛出了无效的比较器断言,而 std::sort 只接受 true 或 false 以便具有弱严格排序。

通过将函数更改为:

bool compareByX(const Vector2D &a, const Vector2D &b)
{
   return a.x < b.x;
}

一切都按预期进行。

最后确实是一个非常明显的错误。

【讨论】:

  • 严格来说你的答案是错误的。比较器只需要返回可隐式转换为bool 的内容,因此返回int 就可以了。真正的问题是您的比较器同时产生了compareByX(a,b) == truecompareByX(b,a) == true,这意味着没有严格的排序。有关比较器返回 int 但完全没问题的工作示例,请参阅 here
【解决方案2】:

根据sort 的参考,比较器必须:

比较函数对象(即满足比较要求的对象)如果第一个参数小于(即排在前面)第二个参数,则返回​true。 比较函数的签名应该等价于:

bool cmp(const Type1 &a, const Type2 &b);

我猜你真正想要的是以下内容:

   std::sort(points.begin(), points.end(), 
         [] (const Vector2D& a1, const Vector2D&a2){return a1.x < a2.x;}
      );

【讨论】:

  • 引用中的should be 并不准确。有关更精确的声明,请参见 here:“返回类型:可隐式转换为 bool”。无论如何,您加粗的部分是导致问题的原因(返回 intbool 并不重要)
  • @tobi303 是的,但从使用比较器的功能的角度来看,这并不重要。他们看到的是truefalse。只要您知道隐式转换是如何工作的,您就可以为true(或任何其他可隐式转换为布尔值)返回non-zero,这并不重要。感谢您指出该参考!
  • 没问题,我只是看到 OP 自己的回答弄错了这一点,并认为这里也值得一提,以避免误解
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-07-07
  • 1970-01-01
  • 2018-06-30
相关资源
最近更新 更多