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、付费专栏及课程。

余额充值