std::map 自定义类型为key,需重载小于运算符

虽然这个问题从学C++就知道,但最近面试的时候,面试官问如果map要使用自定义类型作为key行不行。 我一想他肯定是要问我实现operator <的问题,然后我说了一个不一定哦~ 不必要哦~ 特此记录一下。

一般来说当申明map对象的时候,需要传入支持绝对小于运算的类型作为key:

#include <iostream>
#include <map>

struct Key {
          
   
  int a;
  int b;

  explicit Key(int x, int y) : a(x), b(y) {
          
   }

  bool operator<(const Key& other) const {
          
   
    if (other.a >= a) {
          
   
      return true;
    }

    if (other.a < a and other.b >= b) {
          
   
      return true;
    }

    return false;
  }
};

std::ostream& operator<<(std::ostream& os, const Key& self) {
          
   
  os << "{" << self.a << ", " << self.b << "}";
  return os;
}

int main() {
          
   
  std::map<Key, int, Less> mp{
          
   {
          
   Key(3, 4), 233}};
  mp.insert({
          
   Key(1, 2), 111});

  for (auto&& i : mp) {
          
   
    const auto [a, b] = i;
    std::cout << a << "->" << b << std::endl;
  }
}
{
          
   1, 2}->111
{
          
   3, 4}->233

我们都知道map在插入,删除,查找时会按照二叉树规律去比较节点的key值,默认会使用Key类型提供的<去标胶对象大小。如果在构造时没有传入第三参数比较运算对象,就调用该对象提供的仿函数替换原有<,或者如果没有重载<将使用该对象。gnu C++ 源码:

template <typename _Key, typename _Tp, typename _Compare = std::less<_Key>,
	    typename _Alloc = std::allocator<std::pair<const _Key, _Tp> > >
    class map
    {
          
    ... };

而有一次我在构造map对象的时候传入了比较运算对象

struct Key {
          
   
  int a;
  int b;
  
  explicit Key(int x, int y) : a(x), b(y) {
          
   }
};

struct Less {
          
   
  // std::map采用此规则,变成了从大到小排
  auto operator()(const Key& x, const Key& y) {
          
   
    if (x.a >= y.a) {
          
   
      return true;
    }

    if (x.a < y.a and x.b >= y.b) {
          
   
      return true;
    }

    return false;
  }
};

{
          
   
  std::map<Key, int, Less> mp{
          
   {
          
   Key(3, 4), 233}}; // 使用Less作为第三参数实例化模板
  mp.insert({
          
   Key(1, 2), 111});
}
{
          
   3, 4}->233
{
          
   1, 2}->111
经验分享 程序员 微信小程序 职场和发展