简体   繁体   English

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

[英]C++ STL map container with class key and class value

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. 我在cplusplus中读到第三个参数是比较一些东西,但我不明白那是什么东西。 Can anyone explain that for me? 任何人都能解释一下吗?

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. 默认情况下,stl映射通过一些排序概念对其中的所有元素进行排序。 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. 有时您无法控制Point类,或者您可能希望在两个不同的映射中使用它,每个映射都定义自己的顺序。 For example one map might sort points by x first and other one might sort by y first. 例如,一个地图可能先按x对点进行排序,而另一个可能先按y排序。 So it might be helpful if the comparison operator is independent of the class Point. 因此,如果比较运算符独立于Point类,则可能会有所帮助。 You can do something like this. 你可以做这样的事情。

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;

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 Point

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à... Etvoilà......

Specializing std::less for Point 专业std::less for Point

I see no point in doing this, but it's always good to know: You can specialize the std::less template structure for your Point class 我认为这样做没有意义,但总是很高兴知道:你可以专门为你的Point类设计std::less模板结构

#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:less is concerned. 至于operator <上面的解决方案,从语义上讲,这个解决方案假设上面定义的顺序是正确的默认顺序,就std:less而言。

Note that the default std::less implementation calls the operator < of the is templated type. 请注意,默认的std::less实现调用operator < of templated类型。 Having one giving different results than the other could be considered as a semantic error. 让一个给出不同于另一个的结果可以被认为是语义错误。

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中使用用户定义的类作为键时,为了确定容器中元素的位置,映射需要Comparison类:一个类,它接受键类型的两个参数并返回一个bool。

It is basically, a comparison functor/ function which compares two key values. 它基本上是一个比较函数/函数,它比较两个键值。

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));
        }
};

What you are saying as third parameter is called "Comparator" in STL. 您所说的第三个参数在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. 但对于您定义的类型,您必须提供它或者编译器如何在map / set等中维护排序顺序。

You don't need third parameter, you just need the operator== and operator< 您不需要第三个参数,只需要operator==operator<

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;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM