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

发布于 2024-11-28 08:15:49 字数 405 浏览 1 评论 0原文

所以假设我有一个像这样的类:

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

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

map<Point, Point> m;

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

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

挥剑断情 2024-12-05 08:15:49

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

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

默认情况下,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;

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.

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;
原谅过去的我 2024-12-05 08:15:49

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

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

为 Point 重载 运算符 <

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

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

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

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

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

提供函子

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

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

函子必须具有以下签名:

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

因此,对于我的测试,我只编写了以下内容:

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

并在我的映射中使用了它:

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

Et voilà...

专门化 std::lessPoint

我认为这样做没有意义,但知道总是好的:您可以专门化 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()) ;
        }
    } ;
}

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

至于上面的运算符 < 解决方案,从语义上来说,该解决方案假设上面定义的顺序对于 std:less 而言是正确的默认顺序。

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

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

This can be done in different ways :

Overload the 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à...

Specializing 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

#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.

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.

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

初心 2024-12-05 08:15:49

当您使用用户定义的类作为 std::map 中的键时,为了确定元素在容器中的位置,地图需要 Comparison 类:该类接受两个键类型参数并返回 bool。

它基本上是一个比较函子/函数,用于比较两个键值。

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.

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

善良天后 2024-12-05 08:15:49

您不需要第三个参数,只需要 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;
}

You don't need third parameter, you just need the operator== and 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;
}
不顾 2024-12-05 08:15:49

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

class Point{

    private:
        int x, y;

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

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

class Point{

    private:
        int x, y;

    public:
        bool operator<( const Point& other) const{
            return ((x < other.x) || (y < other.y));
        }
};
一杆小烟枪 2024-12-05 08:15:49

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

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文