erase()函數(shù)的功能是用來刪除容器中的元素
函數(shù)原型:
iterator erase(iterator where);
iterator erase(iterator first,iterator last);
basic_string& erase(size_type p0=0,size_type n=np);
刪除某個容器里的某個元素:c.erase(T);
看似一個簡單的動作,然而對不同類型的容器,內(nèi)部卻做了截然不同的事情,后面介紹。
假設(shè)有這樣一個題目,將某個容器中所有滿足條件N == X的元素刪除,按照常規(guī)的思路應(yīng)該有類似這樣的代碼:
// 假設(shè)Container和container分別表示一種容器和對應(yīng)的一個對象
Container<T>::iterator it;
for (it = container.begin(); it != container.end(); ++it) {
if (N == X)
container.erase(it);
}
然而這樣的代碼對于任一種容器都是錯誤的
容器按內(nèi)存分配方式可以分為鏈表容器和數(shù)組容器。
所謂的鏈表容器指的是一種表現(xiàn)方式,包括list、slist等這樣基于節(jié)點的容器(動態(tài)分配內(nèi)存塊)和set、map、multiset、multimap等關(guān)聯(lián)容器(平衡樹實現(xiàn)),而數(shù)組容器指的是在一塊連續(xù)的內(nèi)存上保存元素的連續(xù)內(nèi)存容器,比如vector、deque、string等。
OK,現(xiàn)在說說erase對他們的操作,鏈表容器以list為例,當(dāng)執(zhí)行container.erase(it)時,確實第一個滿足條件的元素刪除了,但這時it指針已經(jīng)被刪除了,它也不指向任何元素了,所以也只能到此為止了,也就是說上面的代碼對于鏈表容器來說只能正確刪除第一個滿足條件的元素,針對這個問題我們首先想到的就是在刪除指針之前,給其做個備份,很好,不錯的主意,我們一般采用的方法是建立個臨時變量,這個臨時變量可以在程序循環(huán)中適當(dāng)?shù)奈恢檬褂?,看下列代碼實現(xiàn),是將這個臨時變量直接建立在erase實現(xiàn)里,這樣做更簡潔,也顯得專業(yè)些
(以刪除int型鏈表中所有偶數(shù)為例,也是大家都喜歡的一個例子):
list<int>::iterator it;
for (it = lt.begin(); it != lt.end(); ) {
if (*it % 2 == 0)
lt.erase(it++);
else
++it;
}
鏈表容器使用erase刪除節(jié)點還有一個特點,就是會將下一個元素的地址返回,所以也可以這樣實現(xiàn):
list<int>::iterator it;
for (it = lt.begin(); it != lt.end(); ) {
if (*it % 2 == 0)
it = lt.erase(it);
else
++it;
}
當(dāng)然用list容器本身提供的算法也是個不錯的主意(掛回調(diào)):
bool evenNumber(int n)
{
return (n % 2 == 0);
}


lt.remove_if(evenNumber);
數(shù)組容器以vector為例,當(dāng)執(zhí)行container.erase(it)時,和上面提到的一樣,第一個滿足條件的元素刪除了,但這時數(shù)組容器不允許中間有“空隙”,所以會做個大動作,就是將被刪元素后面所有的元素前移(參考STL源碼),而數(shù)組容器記錄的是下標(biāo),所以刪除元素后,當(dāng)前下標(biāo)定位的元素也就順理成章的變成了原有隊列中的下一個元素,同樣以刪除偶數(shù)為例,代碼如下:
vector<int>::iterator it = v.begin();
for (it = v.begin(); it != v.end(); ) {
if (*it % 2 == 0)
v.erase(it);
else
++it;
}
也可以使用reverse_iterator迭代器,并且在某些刪除操作中會有更好的效率(因為它會使上面提到的“大動作”變小一些):
vector<int>::reverse_iterator ri = v.rbegin();
for ( ; ri != v.rend(); ) {
if (*ri % 2 == 0)
v.erase((++ri).base());
else
++ri;
}