for循环中调用vector容器erase函数
代码示例
Code: Select all
int main(){
vector<int> a;
a.push_back(3);
a.push_back(2);
a.push_back(3);
a.push_back(3);
a.push_back(5);
vector<int>::iterator b;
int x = 3;
for(b=a.begin();b!=a.end();b++)
{
if(*b==x){
b=a.erase(b);
}
}
for(b=a.begin();b!=a.end();b++)
{
printf("value=%d\n", *b);
}
return 0;
}
现象&后果
上面代码的目的是,使用迭代器循环删除vector中所有的3,但你会发现并不是所有的3都被删除掉了。
Bug分析
上述代码主要问题是对容器类vector的erase函数理解不够。代码中调用的erase函数在删除当前元素b后,返回b后面的元素。在上述代码的vector中,一开始有3个3,其中后两个3是连续的,在删除第二个3之后,erase函数返回的下一个元素还是3,然而代码运行到循环的b++时,就略过了这个3,从而造成不是所有的3都被删除。
正确的做法是,在删除元素的之后,由于erase函数已经自动跳到下一个元素,跳过接下来循环的b++语句。
正确代码
Code: Select all
int main(){
vector<int> a;
a.push_back(3);
a.push_back(2);
a.push_back(3);
a.push_back(3);
a.push_back(5);
vector<int>::iterator b;
int x = 3;
for(b=a.begin();b!=a.end();)
{
if(*b==x){
b=a.erase(b);
}else{
b++;
}
}
for(b=a.begin();b!=a.end();b++)
{
printf("value=%d\n", *b);
}
return 0;
}
编程建议
在对容器类元素进行增、删操作时,一定要注意增、删操作的返回值和迭代器指示器是否发生变化,必要的时候需要进行修正。