带有类键和类值的 C++ STL 映射容器

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6973406/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 21:03:38  来源:igfitidea点击:

C++ STL map container with class key and class value

c++mapcontainers

提问by petermlm

So suppose I have a class like this one:

所以假设我有一个这样的课程:

class Point
{
   private:
      int x, y;
   public:
      void setX(int arg_x) { x = arg_x; }
      void sety(int arg_y) { y = arg_y; }
      int getX() const { return x; }
      int gety() const { return y; }
};

Now I want to have a map like this one:

现在我想要一张这样的地图:

map<Point, Point> m;

But I need a third parameter. I read in cplusplus that this third parameter is to compare something, but I didn't understand what that something was. Can anyone explain that for me?

但我需要第三个参数。我在 cplusplus 中读到这第三个参数是为了比较某些东西,但我不明白那是什么东西。谁能为我解释一下?

回答by parapura rajkumar

You can extend your class with such a method if you don't need a separate compare function

如果您不需要单独的比较函数,您可以使用这样的方法扩展您的类

class Point
{
   private:
      int x, y;
   public:

      bool operator<( const Point& other) const
      {
          if ( x == other.x )
          {
              return y < other.y;
          }

          return x < other.x;
      }
};

By default the stl map orders all elements in it by some notion of ordering. In this case this operator is used. Sometimes you dont have control over the Point class or you might want to use it in two different maps each defines its own ordering. For example one map might sort points by x first and other one might sort by y first. So it might be helpful if the comparison operator is independent of the class Point. You can do something like this.

默认情况下,stl 映射通过某种排序概念对其中的所有元素进行排序。在这种情况下,使用此运算符。有时您无法控制 Point 类,或者您可能希望在两个不同的地图中使用它,每个地图都定义了自己的排序。例如,一张地图可能会先按 x 对点进行排序,而另一张地图可能会先按 y 对点进行排序。因此,如果比较运算符独立于 Point 类,则可能会有所帮助。你可以做这样的事情。

class Point
{
   public:
      int x, y;
};


struct PointComparer
{
    bool operator()( const Point& first , const Point& second) const
    {
        if ( first.x == second.x )
        {
            return first.y < second.y;
        }

        return first.x < second.x;
    }
};

map<Point, Point , PointComparer> m;

回答by paercebal

What you need is to define an ordering of Point items.

您需要的是定义 Point 项的排序。

This can be done in different ways :

这可以通过不同的方式完成:

Overload the operator <for Point

重载operator <for 点

You can provide an overload of the <operator, whose prototype is :

您可以提供<运算符的重载,其原型为:

bool operator < (const Point & p_lhs, const Point & p_rhs) ;

For example, for my tests, I used the following one :

例如,对于我的测试,我使用了以下一个:

bool operator < (const Point & p_lhs, const Point & p_rhs)
{
    if(p_lhs.getX() < p_rhs.getX()) { return true ; }
    if(p_lhs.getX() > p_rhs.getX()) { return false ; }
    return (p_lhs.getY() < p_rhs.getY()) ;
}

This is the easiest way, but it assumes, semantically, that the ordering defined above is the right default one.

这是最简单的方法,但它在语义上假设上面定义的顺序是正确的默认顺序。

Providing a functor

提供函子

If you are unwilling to provide a <operator, or want to have multiple maps, each one with its own ordering, your solution is to provide a functor to the map. This is the third template parameter defined for the map:

如果你不愿意提供一个<操作符,或者想要有多个映射,每个映射都有自己的顺序,你的解决方案是为映射提供一个函子。这是为地图定义的第三个模板参数:

template < class Key, class T, class Compare = less<Key>,
       class Allocator = allocator<pair<const Key,T> > > class map;

The functor must have the following signature :

函子必须具有以下签名:

struct MyCompareFunctor
{
    bool operator() (const Point & p_lhs, const Point & p_rhs)
    {
       // the code for comparison
    }
} ;

So, for my tests, I just wrote the following :

所以,对于我的测试,我只写了以下内容:

struct MyCompare
{
    bool operator() (const Point & p_lhs, const Point & p_rhs)
    {
        if(p_lhs.getX() > p_rhs.getX()) { return true ; }
        if(p_lhs.getX() < p_rhs.getX()) { return false ; }
        return (p_lhs.getY() > p_rhs.getY()) ;
    }
} ;

And used it in my map:

并在我的地图中使用它:

std::map<Point, Point, MyCompare> map ;

Et voilà...

等等……

Specializing std::lessfor Point

专业std::lessPoint

I see no point in doing this, but it's always good to know: You can specialize the std::lesstemplate structure for your Pointclass

我认为这样做没有意义,但是知道总是好的:您可以std::less为您的Point班级专门设计模板结构

#include <functional>

namespace std
{
    template<>
    struct less<Point> : binary_function <Point,Point,bool>
    {
        bool operator() (const Point & p_lhs, const Point & p_rhs)
        {
            if(p_lhs.getX() < p_rhs.getX()) { return true ; }
            if(p_lhs.getX() > p_rhs.getX()) { return false ; }
            return (p_lhs.getY() < p_rhs.getY()) ;
        }
    } ;
}

This has the same effect as overloading the operator <, at least, as far as the map is concerned.

operator <至少,就地图而言,这与重载 具有相同的效果。

As for the operator <solution above, semantically, this solution assumes that the ordering defined above is the right default one as far as std:lessis concerned.

至于operator <上面的解决方案,从语义上讲,这个解决方案假设上面定义的排序是正确的默认排序std:less

Note that the default std::lessimplementation calls the operator <of the is templated type. Having one giving different results than the other could be considered as a semantic error.

请注意,默认std::less实现调用operator <is 模板化类型。一个给出与另一个不同的结果可以被认为是语义错误。

回答by Alok Save

When you are using a user defined class as key in std::map, in order to determine the position of the elements in the container the map needs the Comparison class: A class that takes two arguments of the key type and returns a bool.

当您使用用户定义的类作为std::map 中的键时,为了确定容器中元素的位置,映射需要比较类:该类采用键类型的两个参数并返回一个布尔值。

It is basically, a comparison functor/ function which compares two key values.

它基本上是比较两个键值的比较函子/函数。

回答by J-16 SDiZ

You don't need third parameter, you just need the operator==and operator<

你不需要第三个参数,你只需要operator==andoperator<

bool operator<(const Point& other) const{
      if ( x == other.x )
          return y < other.y;
      return x < other.x;
}
bool operator==(const Point& other) const{
      return x == other.x && y == other.y;
}

回答by thalesfc

I think the code above gives a little upgrade to @parapura rajkumar's solutions.

我认为上面的代码对@parapura rajkumar 的解决方案进行了一些升级。

class Point{

    private:
        int x, y;

    public:
        bool operator<( const Point& other) const{
            return ((x < other.x) || (y < other.y));
        }
};

回答by Player

What you are saying as third parameter is called "Comparator" in STL. For default types as keys youy don't need to provide one as compiler does that job for you. But for your-defined types you have to provide it OR else how would compiler maintain the sort order in map/set etc.

您所说的第三个参数在 STL 中称为“比较器”。对于作为键的默认类型,您不需要提供一个,因为编译器会为您完成这项工作。但是对于您定义的类型,您必须提供它,否则编译器将如何维护 map/set 等中的排序顺序。