vector中刪除的注意事項


erase的函數原型有兩種形式:

iterator erase(iterator position);
iterator erase(iterator first, iterator last);

例如有一個類A,

class A
{
public:
    int id;
    A(void);
    ~A(void);
};

定義vector<A*> vec

for (int i=0; i<10; i++)
{
    A *p = new A();
    p->id = i;
    vec.push_back(p);
}

下面要刪除vec中id為5的元素:

for(vector<A*>::iterator iter=vec.begin(); iter!=vec.end(); iter++)
{
    if(5 == (*iter)->id)
    {
        delete *iter;
        veci.erase(iter);
    }
}

初看這段代碼沒什么問題,實際上其中存在很大的問題;當調用erase方法后,iter就變成了一個野指針,繼續循環iter++就出錯了。

那我們繼續修改代碼:

for(vector<A*>::iterator iter=vec.begin(); iter!=vec.end(); iter++)
{
    if(5 == (*iter)->id)
   {
        delete *iter;
        iter = veci.erase(iter);
    }
}

erase返回值是這樣的:An iterator that designates the first element remaining beyond any elements removed, or a pointer to the end of the vector if no such element exists

仔細閱讀上面的代碼實際上也有問題,首先代碼不能刪除連續兩個為5的元素,因為刪除第一個之后,iter指向第二個,自增后,就指向了第二個后面了;其次如果元素5位於vector最后,刪除后iter自增也會出錯。

那么正確的寫法可以如下:

for(vector<A*>::iterator iter=vec.begin(); iter!=vec.end(); )
{
    if(5 == (*iter)->id)
   {
        delete *iter;
        iter = veci.erase(iter);
    }
    else
    {
        iter++;
    }
}

這樣就可以解決連續兩個相同元素的問題,同時將要刪除的元素位於最后的話,也不會有問題,因為刪除后,erase返回vector.end()。

其實還可以采用另一種方法,在STL的算法中有一個函數remove,這個函數可以將迭代器范圍內的等於某個值的元素“刪除“(這里的刪除是不改變容器的 大小,只是將一些不滿足條件的元素前移,這樣的話保留的元素都移到了容器的前面,而remove正好就指向這些保留元素后的第一個元素,而后面的就是要刪 除的。)然后執行erase操作就可以了

void remove_v2(vector<int>& v,int val){
    v.erase(   remove(v.begin(),v.end(),val),       v.end()     );
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM