map使用时的一个小陷阱

在STL中,map是一种非常灵活的关联容器,在使用map时一定要正确定义_Kty及_Pr。

map在定义如下:

template<class _Kty, class _Ty, class _Pr = less<_Kty>, class _Alloc = allocator<pair<const _Kty, _Ty> > >
 class map

要实例化一个map首先要确定_Kty与_Ty的类型,其中_Kty为map的键值类型,_Ty为map的数据区的数据类型,_Pr为map比较键值的函数类(默认使用操作符“<”),而_Alloc 为map的配置器(默认使用系统配置器)。在一般情况下,我们只需要确定_Kty与_Ty就可实例化一个map对象。

当实例一个map容器std::map<key,ty> simMap;时,要保存key的操作符“<”可以正常工作,并且保证key类型的数据具有顺序性。

如下是一个错误的定义:

         class  CMapRetryData
        {
        
public :
            
//  键类型
            typedef  struct  _tagMapItem 
            {
                unsigned 
long     m_ulTick;
                unsigned 
char     m_ucRetryCount;
                std::auto_ptr
< const  SENDDATA >     m_pSendData;
            
public :
                _tagMapItem()
                {
                    m_ulTick    
=  ::GetTickCount();
                    m_ucRetryCount    
=   0 ;
                    
// m_pSendData    = NULL;
                }
                _tagMapItem( 
const  _tagMapItem &  v_source )
                {
                    m_ulTick    
=  v_source.m_ulTick;
                    m_ucRetryCount    
=  v_source.m_ucRetryCount;

                    
const  SENDDATA *     pSour;
                    SENDDATA
*  pDest;
                    m_pSendData    
=  std::auto_ptr < const  SENDDATA > ( new  SENDDATA);
                    pSour    
=  v_source.m_pSendData. get ();
                    
if ( NULL  !=  pSour )
                    {
                        pDest    
=  const_cast < SENDDATA *> (m_pSendData. get ());
                        ::memcpy( pDest, pSour, 
sizeof (SENDDATA) );
                    }
                    
else
                    {
                        m_pSendData.reset();
                    }
                }
                
~ _tagMapItem()
                {
                    m_pSendData.reset();
                }
            } CMapItem;
            
//  内容类型
            typedef  struct  _tagMapKey
            {
                unsigned 
long     m_ulTerminaID;
                unsigned 
char     m_ucBussType;
                unsigned 
char     m_ucDataType;
            
public :
                _tagMapKey()
                {
                    m_ulTerminaID    
=   0 ;
                    m_ucBussType    
=   0 ;
                    m_ucDataType    
=   0 ;
                }
                _tagMapKey( 
const  _tagMapKey &  v_source )
                {
                    m_ulTerminaID    
=  v_source.m_ulTerminaID;
                    m_ucBussType    
=  v_source.m_ucBussType;
                    m_ucDataType    
=  v_source.m_ucDataType;
                }
                
~ _tagMapKey()
                {
                }

                
bool   operator   ==  (  const  _tagMapKey &  v_source )  const
                {
                    
return  ((m_ulTerminaID  ==  v_source.m_ulTerminaID)  &&
                            (m_ucBussType 
==  v_source.m_ucBussType)  &&
                            (m_ucDataType 
==  v_source.m_ucDataType));
                }
                
bool   operator   <  ( const  _tagMapKey &  v_source )  const
                {
                    // 这里是问题所在
                    
return  ((m_ulTerminaID  <  v_source.m_ulTerminaID)  &&
                            (m_ucBussType 
<  v_source.m_ucBussType)  &&
                            (m_ucDataType 
<  v_source.m_ucDataType));
                }
                
bool   operator   !=  (  const  _tagMapKey &  v_source )  const
                {
                    
return  ((m_ulTerminaID  !=  v_source.m_ulTerminaID)  ||
                            (m_ucBussType 
!=  v_source.m_ucBussType)  ||
                            (m_ucDataType 
!=  v_source.m_ucDataType));
                }
            } CMapKey;
            
//  比较类
             class  CCompare
            {
            
public :
                
bool   operator () (  const  CMapKey  & v_key1,  const  CMapKey  & v_key2 )  const
                {
                    // 这里是问题所在
                    
return  ((v_key1.m_ulTerminaID  >=  v_key2.m_ulTerminaID)  &&
                            (v_key1.m_ucBussType 
>=  v_key2.m_ucBussType)  &&
                            (v_key1.m_ucDataType 
>=  v_key2.m_ucDataType));
                }
            };
            typedef std::map
< CMapKey, CMapItem /* , CCompare */ >  CDataMap;
        
public :
            CMapRetryData()
                
// : m_dataMap()
            {
            }
            
~ CMapRetryData()
            {
                m_dataMap.clear();
            }
        
private :
            
//  Map类
            CDataMap    m_dataMap;
        
public :
            CMapItem
&   operator [] (  const  CMapKey &  v_key )
            {
                
return     m_dataMap[v_key];
            }

            
void  DeleteItem( CMapKey &  v_key )
            {
                m_dataMap.erase(v_key);
            }

            
const  SENDDATA *  FindOverTime();
        };

这段代码是一个map的应用,这里map的键值类重载了操作符“<”,也实现了一个比较类CCompare。这里出现的问题j是操作符重符后的键值类型不具有顺序性,例:

 

CMapRetryData::CMapKey    key1, key2;
key1.m_ulTerminaID    
=   1 ;
key1.m_ucBussType    
=   0x19 ;
key1.m_ucDataType    
=   0x01 ;

key2.m_ulTerminaID    
=   1 ;
key2.m_ucBussType    
=   0x19 ;
key2.m_ucDataType    
=   0x02 ;

//  有如下表达式成立
( key1  <  key2 )  ==   false ;
( key2 
<  key1 )  ==   false ;

上述代码说明CMapKey类型没有顺序性,这产生的后果就是不能通过已知的键值查找键值对应的数据内容。

因此,将出错部分进行如下修改:

 

             //  键类型
            typedef  struct  _tagMapKey
            {
                unsigned 
long     m_ulTerminaID;
                unsigned 
char     m_ucBussType;
                unsigned 
char     m_ucDataType;
            
public :
                _tagMapKey()
                {
                    m_ulTerminaID    
=   0 ;
                    m_ucBussType    
=   0 ;
                    m_ucDataType    
=   0 ;
                }
                _tagMapKey( 
const  _tagMapKey &  v_source )
                {
                    m_ulTerminaID    
=  v_source.m_ulTerminaID;
                    m_ucBussType    
=  v_source.m_ucBussType;
                    m_ucDataType    
=  v_source.m_ucDataType;
                }
                
~ _tagMapKey()
                {
                }

                
bool   operator   ==  (  const  _tagMapKey &  v_source )  const
                {
                    
return  ((m_ulTerminaID  ==  v_source.m_ulTerminaID)  &&
                            (m_ucBussType 
==  v_source.m_ucBussType)  &&
                            (m_ucDataType 
==  v_source.m_ucDataType));
                }
                
bool   operator   <  ( const  _tagMapKey &  v_source )  const
                {
                    
return  (m_ulTerminaID  !=  v_source.m_ulTerminaID  ?  m_ulTerminaID  <  v_source.m_ulTerminaID :
                                (m_ucBussType 
!=  v_source.m_ucBussType  ?  m_ucBussType  <  v_source.m_ucBussType :
                                    (m_ucDataType 
<  v_source.m_ucDataType)));
                    
// return ((m_ulTerminaID < v_source.m_ulTerminaID) &&
                    
//         (m_ucBussType < v_source.m_ucBussType) &&
                    
//         (m_ucDataType < v_source.m_ucDataType));
                }
                
bool   operator   !=  (  const  _tagMapKey &  v_source )  const
                {
                    
return  ((m_ulTerminaID  !=  v_source.m_ulTerminaID)  ||
                            (m_ucBussType 
!=  v_source.m_ucBussType)  ||
                            (m_ucDataType 
!=  v_source.m_ucDataType));
                }
            } CMapKey;
            
//  比较类
             class  CCompare
            {
            
public :
                
bool   operator () (  const  CMapKey  & v_key1,  const  CMapKey  & v_key2 )  const
                {
                    
return  (v_key1.m_ulTerminaID  !=  v_key2.m_ulTerminaID  ?  v_key1.m_ulTerminaID  <  v_key2.m_ulTerminaID :
                                (v_key1.m_ucBussType 
!=  v_key2.m_ucBussType  ?  v_key1.m_ucBussType  <  v_key2.m_ucBussType :
                                    (v_key1.m_ucDataType 
<  v_key2.m_ucDataType)));
                    
// return ((v_key1.m_ulTerminaID >= v_key2.m_ulTerminaID) &&
                    
//         (v_key1.m_ucBussType >= v_key2.m_ucBussType) &&
                    
//         (v_key1.m_ucDataType >= v_key2.m_ucDataType));
                }
            };
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值