C++ STL map 中关于自定义Key的约束

开始之前,先看一下std::map的模板声明:

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

通常情况下,我们这样定义并且使用map

std::map<int, int> map;
map.insert({1,2});

如下,现在我们用自己定义的类类型作为key

#include <iostream>
#include <map>

class Dylan
{
public:
    Dylan() { name = ""; addr = ""; }
    Dylan(std::string na, std::string ad) : name(na), addr(ad) {};
    const string getName() const { return name; }
    const string getAddr() const { return addr; }
    
private:
    std::string name;
    std::string addr;
    int age = 0;
};
int main()
{
    std::map<Dylan, int> map;
    Dylan dy("111","222");
    map.insert({dy,1}); //这句会引发编译时的错误,如果没有这句插入操作,则在vs环境下可编译通过
}

我们将收到编译错误:

以vs2019 环境为例,上面的代码会收到如下error:

error C2676: binary '<': 'const _Ty' does not define this operator or a conversion to a type acceptable to the predefined operator

这是什么原因呢?这是由于map的底层数据结构决定的,map的底层结构是一棵红黑树,为有序结构;所以在向map中插入数据的时候需比较插入数据的大小,也就是说需要待插入数据支持比较大小。

要让class Dylan类的对象支持比较大小,有两种方法:

方法一  在类中重载小于号运算符(<)

class Dylan
{
public:
    Dylan() { name = ""; addr = ""; }
    Dylan(std::string na, std::string ad) : name(na), addr(ad) {};
    const string getName() const { return name; }
    const string getAddr() const { return addr; }
    
    bool operator<(const Dylan& dy1) const { return this->getName() < dy1.getName(); }
    //重载小于号运算符,注意切记函数声明为const类型
private:
    std::string name;
    std::string addr;
    int age = 0;
};

在这里有个要注意的地方,就是重载小于号的函数必须声明为const函数,否则会收到如下error:

error C2678: binary '<': no operator found which takes a left-hand operand of type 'const _Ty' (or there is no acceptable conversion)

message : while compiling class template member function 'bool std::less<_Kty>::operator ()(const _Ty &,const _Ty &) const'

map默认提供一个仿函数,用来比较带插入元素的大小,如果不自定义指定,map就会在std::less中调用待插入元素自己的小于号运算符去比较大小,由于std::less元素是const函数,所以我们自己在实现重载小于号运算符时,也要记住将函数声明为const类型。std::less是const的是由map的构造函数声明决定的,他的构造函数的第三个参数,要求传入一个比较大小的函数指针,这个参数是const参数(即const函数)

方法二 自定义less函数

class Dylan {.....}
class myless_than
{
public:
    bool operator()(const Dylan& dy1, const Dylan& dy2) const//也得是const的
    {
        return dy1.getName() < dy2.getName();
    }
};

int main()
{
    std::map<Dylan, int, myless_than> map;
    Dylan dy("1111","2222");
    map.insert({dy,1});
}

注意,重载()运算符的函数也得是const的,原因和方法一中的原因类似,否则会受到如下error:

error C3848: expression having type 'const myless_than' would lose some const-volatile qualifiers in order to call 'bool myless_than::operator ()(const Dylan

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值