关于vector的erase问题处理

Vectorerase成员函数有许多容易导致问题的情况.其中以迭代器失效问题最为常见.

关于迭代器的失效问题,以及erase如何删除vector中指定值(可能不止一个),我曾今也对erase的使用情况和内容结合起来写过一些字.

博文地址:http://blog.csdn.net/yuanweihuayan/article/details/6790516

似乎对于删除的解析已经够全面了.可是最近在项目里面发现一个很奇怪的问题,跟踪了很久都没有发现是什么问题导致的.

今天知道了问题的原因,但是为什么会这样,我还是不清楚.看来STL这块还需加大力度学习它.

源码如下:


struct Usr
{
string strUiD;	
string strSrnName;
string strNickName;	 
string strDesc;	 
string strGender;	 
string strIcon;	 
string strVtitle;	 
string strVType;	 
Usr()
{    
strUiD = "";
strSrnName = "";
strNickName = "";
strDesc = "";
strGender = "";
strIcon = "";
strVtitle = "";
strVType = "";
}
Usr( string strUid,string strSrnName,string strNickName )
{
SetData( strUid,strSrnName,strNickName );
}
void SetData( string strUid,string strSrnName,string strNickName )
{
this->strUiD = strUid;
this->strSrnName = strSrnName;
this->strNickName = strNickName;
strDesc = "";
strGender = "";
strIcon = "";
strVtitle = "";
strVType = "";
}
void operator=( const Usr& usr )
{
if ( usr.strUiD == strUiD)
{
return;
}
strSrnName = usr.strSrnName;
strNickName = usr.strNickName;
strDesc = usr.strDesc;
strGender = usr.strGender;
strIcon = usr.strIcon;
strVtitle = usr.strVtitle;
strVType = usr.strVType;
}
bool operator==( Usr& usr )
{
if ( usr.strUiD == strUiD )
{
return true;
}
return false;
}
bool isEqual( Usr usr )
{
if ( usr.strUiD == strUiD )
{
return true;
}
return false;
}
};
vector<Usr> vecUsr;
Usr usr( "10001","ysl","袁孙良" );
vecUsr.push_back( usr );
usr.SetData( "10002","zxy","张学友" );
vecUsr.push_back( usr );
usr.SetData( "10003","ldh","刘德华" );
vecUsr.push_back( usr );
for ( vector<Usr>::iterator iterUsr = vecUsr.begin();iterUsr != vecUsr.end();iterUsr ++ )
{
if ( iterUsr->strUiD == "10001" )
{
vector<Usr>::iterator iterEnd = vecUsr.erase( iterUsr );
if ( iterEnd != vecUsr.end() )
{
TRACE("success");
break;
}
}
}
TRACE( "\n***************************************************************\n" );
for ( vector<Usr>::iterator iterTemp= vecUsr.begin();iterTemp != vecUsr.end();iterTemp ++ )
{
CString strFormat;
strFormat.Format( "编号:%s,  昵称:%s\n",iterTemp->strUiD.c_str(),iterTemp->strNickName.c_str() );
TRACE( strFormat.GetBuffer() );
}


先看输出结果:

success

***************************************************************

编号:10001,  昵称:张学友

编号:10002,  昵称:刘德华

这个结果很令人费解.

strUiD好像整体往下"移动"一位

采用单步调试或者TRACE来检查程序的数据情况,(这里我采用TRACE,原因很简单,单步调试对迭代器不起啥作用).

加入的调试信息如下:

vector<Usr> vecUsr;
Usr usr( "10001","ysl","袁孙良" );
vecUsr.push_back( usr );
usr.SetData( "10002","zxy","张学友" );
vecUsr.push_back( usr );
usr.SetData( "10003","ldh","刘德华" );
vecUsr.push_back( usr );
TRACE( "\n***************************************************************\n" );
for ( vector<Usr>::iterator iterTemp= vecUsr.begin();iterTemp != vecUsr.end();iterTemp ++ )
{
CString strFormat;
strFormat.Format( "编号:%s,  昵称:%s\n",iterTemp->strUiD.c_str(),iterTemp->strNickName.c_str() );
TRACE( strFormat.GetBuffer() );
}
TRACE( "\n***************************************************************\n" );
for ( vector<Usr>::iterator iterUsr = vecUsr.begin();iterUsr != vecUsr.end();iterUsr ++ )
{
if ( iterUsr->strUiD == "10001" )
{
vector<Usr>::iterator iterEnd = vecUsr.erase( iterUsr );
if ( iterEnd != vecUsr.end() )
{
CString strFormat;
strFormat.Format( "编号:%s,  昵称:%s\n",iterEnd->strUiD.c_str(),iterEnd->strNickName.c_str() );
TRACE( strFormat.GetBuffer() );
break;
}
}
}
TRACE( "\n***************************************************************\n" );
for ( vector<Usr>::iterator iterTemp= vecUsr.begin();iterTemp != vecUsr.end();iterTemp ++ )
{
CString strFormat;
strFormat.Format( "编号:%s,  昵称:%s\n",iterTemp->strUiD.c_str(),iterTemp->strNickName.c_str() );
TRACE( strFormat.GetBuffer() );
}


程序的执行结果如下:

***************************************************************

编号:10001,  昵称:袁孙良

编号:10002,  昵称:张学友

编号:10003,  昵称:刘德华

***************************************************************

编号:10001,  昵称:张学友

***************************************************************

编号:10001,  昵称:张学友

编号:10002,  昵称:刘德华

结果令人诧异,iterEnd返回的本是10001后面的数据,(编号:10002,  昵称:张学友),结果返回id和昵称对不上,更为甚者,ID居然是10001.

很多人看到这个程序很疑惑,为什么代码里面会有这么多的操作符的重载?

这个问题还要追溯到泛型算法.泛型算法很多操作都要重载比较操作符等一系列的操作符.如果我们的程序没有这些操作符.程序无法编译.

一般的C++教材里面之所以不存在重载的问题,主要原因是他的类型一般是简单数据类型;vector<int>,vector<string>..

这些东西系统都内置了比较操作符.所以...

我们把赋值操作符去掉,发现整个程序正常运行.10001记录

程序运行结果如下:

***************************************************************

编号:10001,  昵称:袁孙良

编号:10002,  昵称:张学友

编号:10003,  昵称:刘德华

***************************************************************

编号:10002,  昵称:张学友

***************************************************************

编号:10002,  昵称:张学友

编号:10003,  昵称:刘德华

看到erase函数里面实际上调用了copy,而这个函数会和我们定义的赋值操作符有冲突.具体情况还不是很清楚.这个问题等我深入STL时在做结论.

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值