[求助]还是关于vector的问题,还是高手进吧!!!!

时间:2021-11-01 18:53:22
编译环境:VC6.0

vector<int> vInt;
vector<int>::iterator itor;

vInt.reserve(5);
for ( int i = 0; i < 5; i++ )
{
vInt.push_back( i );
}

for ( i = 0; i < 5; i++ )
{
cout << vInt.at(i) << '\t'; 
}
cout << endl;
         //开始erase特定元素,比如值为4的元素


         
         //指明删除最后一个,成功
          itor = vInt.end()-1;
cout << *itor << endl;
vInt.erase( itor );

但如果换成如下就出现错误:
for ( itor = vInt.begin(); itor != vInt.end(); ++itor )
{
cout << *itor << endl;
if ( *itor == 4 )                   //元素为    4   的erase
{
vInt.erase( itor );
}
}   

请高手解答,如果你认为是erase后itor位置不定的问题,那么下面的代码为什么又是对的呢?
 
         for ( itor = vInt.begin(); itor != vInt.end(); ++itor )
{
cout << *itor << endl;
if ( *itor == 3 )                   //元素为   3    的erase
{
vInt.erase( itor );
}
}        


8 个解决方案

#1


是你使用不当了。
//但如果换成如下就出现错误:
这里: for ( itor = vInt.begin(); itor != vInt.end(); ++itor )
{
cout << *itor << endl;
if ( *itor == 4 )                   //元素为    4   的erase
{
itor = vInt.erase( itor );
if (itor == vInt.end())
{
break;
}
}
}

#2


你忽视了erase的返回值。就是这样而已。

#3


如果itor为end()后,在下一次的for循环中,
itor != vInt.end()不会做判断吗?一旦判断了,循环自己就会中止才对吧。

为什么还要自己多来一遍做判断?

#4


itor为end后,下一次判断前会执行++itor,这样就错了。

其实,删除的动作,应该直接使用算法<algorithm>库来完成的。

itor = find(vInt.begin(), vInt.end(), 3);
if(itor != vInt.end())
  erase(itor);

#5


还是stl的基础问题,给earse函数传一个iterator,删除单前的元素.然后做为参数传入的iterator仍然指向当前偏移量的地址,vector容器会此偏移量将后面的所有元素按位向前copy
一位,巧的是你删除的是vector中的最后一个元素,而且用了循环,于是就出问题了。

for ( itor = vInt.begin(); itor != vInt.end(); ++itor )
{
  if ( *itor == 4 )                   //元素为    4   的erase
  {
vInt.erase( itor );
  }

}
循环里itor 指向vector[4]时找到该元素,删除vector[4]的内容,而后将vector[4]之后的所有元素前移一位,而vector[4]之后只有vector.end()指针,此指针前移,指向vector[4].此时单个for循环结束,执行++itor (在这儿出事的!!),itor指向vector.end()后面一位去了,此时for的结束判断itor != vInt.end(); 永远为真,itor 一直会++下去,形成死循环。

   0    1    2    3    4    vector.end()
                       ↑iter    //删除4
   0    1    2    3    vector.end()   //后面的前移,iter不变,结束for后面的复合语句
                       ↑iter
   0    1    2    3    vector.end()
                                     ↑iter // iter++,出事了,形成死循环,永远for下去


同理如果你要删除的时vector[3],在删除vector[3]后,vector[4]和vector.end()前移,iter指向的是vector[4],此时单个循环结束,iter++,指向vector.end(),itor != vInt.end()为假,结束循环。

#6


一楼正界
进行此步后
if ( *itor == 4 )                   //元素为    4   的erase
{
vInt.erase( itor );
}
itor已为vInt.end(),
再执行++itor当然就无法得到这个判断了itor != vInt.end()

#7


我来解释看你满意不满意,vInt.end()是判断它的结束条件,你看看结束条件是怎么定义的(是容器末元素的后一位置),但是你把4删除以后,itor++以后,会跑到末元素的后一位置的后一位置,你可能认为这也是结束条件,不要认为只要容器没内容就是它的结束位置,一定要记住结束位置是它的末元素的后一位置,这样itor!=vInt.end()就是死循环了,我讲的很罗索,不知道你有没有明白,你删除3的话画个图应该知道了吧

#8


你可以写个if语句
if (vInt.end() == vInt.end()+1)
 cout << "ddd";
else
 cout << "error";
你会发现输出是error,所以你上面那个itor != vInt.end()永远是true,死循环

#1


是你使用不当了。
//但如果换成如下就出现错误:
这里: for ( itor = vInt.begin(); itor != vInt.end(); ++itor )
{
cout << *itor << endl;
if ( *itor == 4 )                   //元素为    4   的erase
{
itor = vInt.erase( itor );
if (itor == vInt.end())
{
break;
}
}
}

#2


你忽视了erase的返回值。就是这样而已。

#3


如果itor为end()后,在下一次的for循环中,
itor != vInt.end()不会做判断吗?一旦判断了,循环自己就会中止才对吧。

为什么还要自己多来一遍做判断?

#4


itor为end后,下一次判断前会执行++itor,这样就错了。

其实,删除的动作,应该直接使用算法<algorithm>库来完成的。

itor = find(vInt.begin(), vInt.end(), 3);
if(itor != vInt.end())
  erase(itor);

#5


还是stl的基础问题,给earse函数传一个iterator,删除单前的元素.然后做为参数传入的iterator仍然指向当前偏移量的地址,vector容器会此偏移量将后面的所有元素按位向前copy
一位,巧的是你删除的是vector中的最后一个元素,而且用了循环,于是就出问题了。

for ( itor = vInt.begin(); itor != vInt.end(); ++itor )
{
  if ( *itor == 4 )                   //元素为    4   的erase
  {
vInt.erase( itor );
  }

}
循环里itor 指向vector[4]时找到该元素,删除vector[4]的内容,而后将vector[4]之后的所有元素前移一位,而vector[4]之后只有vector.end()指针,此指针前移,指向vector[4].此时单个for循环结束,执行++itor (在这儿出事的!!),itor指向vector.end()后面一位去了,此时for的结束判断itor != vInt.end(); 永远为真,itor 一直会++下去,形成死循环。

   0    1    2    3    4    vector.end()
                       ↑iter    //删除4
   0    1    2    3    vector.end()   //后面的前移,iter不变,结束for后面的复合语句
                       ↑iter
   0    1    2    3    vector.end()
                                     ↑iter // iter++,出事了,形成死循环,永远for下去


同理如果你要删除的时vector[3],在删除vector[3]后,vector[4]和vector.end()前移,iter指向的是vector[4],此时单个循环结束,iter++,指向vector.end(),itor != vInt.end()为假,结束循环。

#6


一楼正界
进行此步后
if ( *itor == 4 )                   //元素为    4   的erase
{
vInt.erase( itor );
}
itor已为vInt.end(),
再执行++itor当然就无法得到这个判断了itor != vInt.end()

#7


我来解释看你满意不满意,vInt.end()是判断它的结束条件,你看看结束条件是怎么定义的(是容器末元素的后一位置),但是你把4删除以后,itor++以后,会跑到末元素的后一位置的后一位置,你可能认为这也是结束条件,不要认为只要容器没内容就是它的结束位置,一定要记住结束位置是它的末元素的后一位置,这样itor!=vInt.end()就是死循环了,我讲的很罗索,不知道你有没有明白,你删除3的话画个图应该知道了吧

#8


你可以写个if语句
if (vInt.end() == vInt.end()+1)
 cout << "ddd";
else
 cout << "error";
你会发现输出是error,所以你上面那个itor != vInt.end()永远是true,死循环