关于std::Map容器的一点总结

来源:互联网 发布:网络电视的打开方式 编辑:程序博客网 时间:2024/06/07 16:05

 

 

Map容器的键值如果是C++内置数据类型,Map在构造底层的红黑树时会用到这些内置类型的<操作来进行元素间的比较操作。

但是当Map容器的键值不是内置类型而是自己定义的类型时,比如一个类、一个结构体。此时就要对Map的比较函数做一点处理,这种情况还会有两种情况出现:

第一种即为如果Map的键值是类的对象是,由于类模板是静态编译的,如果自己定义的Map键值没有实现 < 操作符,编译会出错。此时可以定义类的成员函数 bool operator < ( const NodeInfo& rValue )const(注意了这个const不能少)。这样在构造Map的红黑树及针对Map进行find操作时会自动调用到这个自己重载的“<”操作。

第二种情况即为如果Map的键值是类对象的指针时,由于编译器把指针当作32位的整数来处理,此时会存在潜在的错误:不管你自己定义的类中重载了“<”操作符与否,编译都会通过,因为它把指针当作32位整数来看待。但是在针对map进行find操作时不会找到自己想要的结果。此时必须实现自己的比较函数对象,不能再用Map默认的比较函数对象了,比如下面的比较函数对象:

class Compare : public std::binary_function<NodeInfo*,NodeInfo*,bool>

{

public:

bool operator()(const NodeInfo*plValue, constNodeInfo* rValue)

{

return plValue->addr.union_addr_mem.dwAddr < rValue->addr.union_addr_mem.dwAddr;

}

};

 

std::map<NodeInfo*,int,Compare> m_mapList;

这个map类的键值为 NodeInfo* ,值域为int,比较函数为Compare

 

 

针对std::find()std::find_if()的区别,它们的源码如下所示:

_InIt_Find(_InIt _First, _InIt _Last, const _Ty& _Val)

{    // find first matching_Val

_DEBUG_RANGE(_First, _Last);

for (; _First != _Last; ++_First)

if (*_First == _Val)

break;

return (_First);

}

_InIt _Find_if(_InIt _First, _InIt _Last, _Pr _Pred)

{    // find first satisfying_Pred

_DEBUG_RANGE(_First, _Last);

_DEBUG_POINTER(_Pred);

for (; _First != _Last; ++_First)

if (_Pred(*_First))

break;

return (_First);

}

Find()find_if()都是到指定的容器中查找指定的元素。它们在比较元素相同时有不同之处,find()通过“==”操作符进行比较,find_if()则通过模板参数给定的比较函数对象进行比较。这就说明在你自己的类中要重载==操作符,如果你用find()的话,重载operator()操作符,如果你用find_if()的话。

如果容器中存的是对象的指针,想用find()函数来搜索容器中的元素,由于==号的左操作数不是这个类的对象,必须声明友元函数来比较它们(下面说明重载操作符在什么情况下使用友元,什么情况下使用类成员函数)。如下所示:

friend bool operator == ( const NodeInfo* plValue,const NodeInfo&rValue )

{

return plValue->addr.union_addr_mem.dwAddr == rValue.addr.union_addr_mem.dwAddr;

}

当使用find_if()进行操作时,则要根据容器中所存放的内容来定义operator() 操作符。例如:

bool operator () (const NodeInfo rValue )

{

return addr.union_addr_mem.dwAddr== rValue.addr.union_addr_mem.dwAddr;

}

 

bool operator () (const NodeInfo* rValue )

{

return addr.union_addr_mem.dwAddr== rValue->addr.union_addr_mem.dwAddr;

}

 

什么时候定义类成员操作符重载,什么时候定义非类成员操作符重载?

 答:(1)如果一个重载操作符是类成员,那么只有当跟它一起使用的左操作数是该类对象时, 它才会被调用,如果该操作符的左操作数必须是其他类型,那么重载操作符必须是非类成员操作符重载。

 (2C++要求,赋值(=),下标 [ ]),调用(())和成员访问箭头(->)操作符必须被指定为类成员操作符,否则错误。

 

原创粉丝点击