使用std::map做什么?

What is this use of std::map doing?

本文关键字:什么 map std 使用      更新时间:2023-10-16

谁能解释一下我从这个使用std::map的简单程序中得到的输出?请注意,我将p插入到地图中,但没有将q插入到地图中,它说它找到了它们两个,但也说地图中只有一个元素!

#include <map>
#include <iostream>
struct screenPoint {
  float x = 0, y = 0;
  screenPoint(float x_, float y_): x{x_}, y{y_}{}
};
bool operator<(const screenPoint& left, const screenPoint& right){
  return left.x<right.x&&left.y<right.y;
}
std::map<screenPoint, float> positions;
int main(int argc, const char * argv[]) {
  auto p = screenPoint(1,2);
  auto q = screenPoint(2,1);
  positions.emplace(p,3);
  auto f = positions.find(p);
  auto g = positions.find(q);
  if (f == positions.end()){
    std::cout << "f not found";
  } else {
    std::cout << "f found";
  }
  std::cout << std::endl;
  if (g == positions.end()){
    std::cout << "g not found";
  } else {
    std::cout << "g found";
  }
  std::cout << std::endl;
  std::cout << "number elements: " << positions.size() << "n";
  return 0;
}
输出:

f found
g found
number elements: 1

在本例中,问题在于您定义比较函子的方式。这两个元素,pq,有相同的xy,只是倒置了。您的逻辑检查其中一个的x小于另一个的y s。对于这些输入,它永远不会求值为true

试试这个片段:

int main()
{
    auto p = screenPoint(1,2);
    auto q = screenPoint(2,1);
   std::cout << std::boolalpha << (p < q) << " " << (q < p) << std::endl;
}

它将输出

false false

所以p不小于q, q不小于p。就映射而言,这使得它们是等价的。

为了在std::map中使用数据类型,它必须具有称为严格弱排序的特定顺序(https://en.wikipedia.org/wiki/Weak_ordering)。这意味着不等式运算符(<)遵循一组非常特定的规则。但是,您指定的操作符不是弱排序。特别是,给定两个screenPoint s,分别由(1,2)和(2,1)构造的ab,您将看到a < bb < a都是假的。在严格的弱排序中,这将需要暗示a == b,这不是真的!

因为你的不等式运算符不满足严格弱排序的要求,map最终会做一些意想不到的事情。我建议阅读更多关于这个排序的细节,并阅读/思考map为什么需要它。在短期内,可以这样重新定义操作符:

bool operator<(const screenPoint& left, const screenPoint& right){
  if (left.x != right.x) return left.x < right.x;
  else return (left.y < right.y);
}