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);
嗯,其實刪除一個容器中的值的方式還是挺多的。