C++的容器中一般都提供erase函数,此函数接收的参数一般有一个是一个迭代器:
如果删除某一个值的话,我们可能一般都用过:
list<int> c;
// todo insert items
for (list<int>::iterator i = c.begin(); i!= c.end(); ++i)
{
if ((*i)>10)
{
// 如果有一个值大于10,删除之
c.erase(i);
break;
}
}
上述代码在删除一个元素的时候并没有问题。。。但是我们想删除所有大于10的值,于是:
list<int> c;
// todo insert items
for (list<int>::iterator i = c.begin(); i!= c.end(); ++i)
{
if ((*i)>10)
{
// 删除所有大于10的值
c.erase(i);
}
}
满怀希望的编译,运行。。。于是异常发生。。。
啊。。。哦。。。
原来是删除迭代器i后,i所指的元素已经失效了,然后给i++,它已经不在存在了。。。于是绞尽脑汁,出笼了下面的代码:
list<int> c;
// todo insert items
list<int>::iterator nextitr = c.begin();
for (list<int>::iterator i = c.begin();;)
{
if(nextitr == c.end())
break;
++nextitr;
if ((*i)>10)
{
// 如果有一个值大于10,删除之
c.erase(i);
}
i = nextitr;
}
上面的代码很容易理解,即在删除一个迭代器之前,把它的之后的迭代器先存储,然后在下次循环的时候利用之前存储的迭代器。
OK,我们看到上面这段代码可以工作了,行为似乎也还正确,只是。。。代码似乎多了点。我想代码能够少点就好了,逻辑也不要那么麻烦。那么我们看下面的代码(转载自Effective STL)。
list<int> c;
// todo insert items
for (list<int>::iterator i = c.begin(); i!= c.end();)
{
if ((*i)>10)
{
// 如果有一个值大于10,删除之
c.erase(i++);
}
else
i++;
}
嗯。。。高手就是高手(我以前根本没有在意过++i和i++在使用的过程中能有这么大的区别)
好了,最后再提供一个版本,利用list的remove_if函数。
bool fun(int i)
{
if(i>10)
return true;
else
return false;
}
list<int> c;
// todo insert items
c.remove_if(fun);
嗯,其实删除一个容器中的值的方式还是挺多的。