虽然这个问题从学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