2012-12-26 49 views
0

我嘗試使用std ::刪除(我讀過關於這個算法herehere)和目錄::擦除和性病的組合移除從列表中elemetns(指向一個名爲類型)::找到。我應該使用std :: remove從列表中刪除元素嗎?

下面是我寫的這個目的的代碼:

#include <iostream> 

#include <list> 
#include <functional> 
#include <string> 
#include <algorithm> 


class NamedType 
{ 
    std::string name_; 

    public: 
     NamedType (const char* name) 
      : 
       name_(name) 
     {}  

     void info() 
     { 
      std::cout << name_ << ": NamedType::update()" << std::endl; 
     } 
}; 

class NamedTypeList 
{ 
    std::list<NamedType*> objectList_; 

    public: 

     void addNamedType(NamedType& o) 
     { 
      NamedType* oPtr = &o; 
      objectList_.push_back(oPtr); 
     } 

     void removeNamedTypeWithFind(NamedType& o) 
     { 
      std::list<NamedType*>::iterator removedNamedType = std::find(
       objectList_.begin(), objectList_.end(), &o); 

      if (removedNamedType != objectList_.end()) 
      { 
       objectList_.erase(removedNamedType); 
      } 
     } 

     void removeNamedType(NamedType& o) 
     { 
      std::remove(objectList_.begin(), objectList_.end(), &o); 
     } 

     void namedObjectsInfo() 
     { 
      std::for_each(objectList_.begin(), objectList_.end(), 
       std::mem_fun(&NamedType::info)); 
     } 
}; 

using namespace std; 

int main() 
{ 
    NamedType o1("o1"); 
    NamedType o2("o2"); 
    NamedType o3("o3"); 
    NamedType o4("o4"); 

    NamedTypeList objectList1; 
    NamedTypeList objectList2; 

    objectList1.addNamedType(o1); 
    objectList1.addNamedType(o2); 
    objectList1.addNamedType(o3); 
    objectList1.addNamedType(o4); 

    objectList2.addNamedType(o1); 
    objectList2.addNamedType(o2); 
    objectList2.addNamedType(o3); 
    objectList2.addNamedType(o4); 

    cout << "Registered objects into objectList1:" << endl; 
    objectList1.namedObjectsInfo(); 

    cout << "Registered objects into objectList2:" << endl; 
    objectList2.namedObjectsInfo(); 

    cout << "Removing o2 object from objectList1 with remove" << endl; 

    objectList1.removeNamedType(o2); 
    objectList1.namedObjectsInfo(); 


    cout << "Removing o2 object from objectList2 with std::find" << endl; 

    objectList2.removeNamedTypeWithFind(o2); 
    objectList2.namedObjectsInfo(); 

}; 

我不明白的是爲什麼我得到下面的輸出,當我打電話objectList1.removeNamedType(02);

Removing o2 object from objectList1 with remove 
o1: NamedType::update() 
o3: NamedType::update() 
o4: NamedType::update() 
o4: NamedType::update() 

我無法理解的文檔:我得到的,有顯示範圍的新結束一個NEW_END迭代器,但如果我有多個相同NamedTypes這不工作,那麼。例如。如果我在objectList1中註冊了兩次對象o2,它將是可見的,並且它的成員函數將由namedObjectsInfo()方法調用,因爲它遍歷所有元素(它看不到new_end迭代器)。

如果我的理解是正確的,應該我甚至使用std ::刪除從容器,或性病的組合刪除元素::查找和列表::在這種情況下刪除?

回答

5

當一個容器都有自己remove方法,爲std::list,則應該用這個來代替std::remove。對於沒有remove方法的容器,應該使用此處其他答案中描述的擦除刪除慣用法。

3

std::remove所以你最終與你的迭代器區間的結束「多餘的」元素不更新容器結構本身。爲了徹底清理容器,你需要結合刪除和擦除:

void removeNamedType(NamedType& o) 
    { 
     objectList_.erase(std::remove(objectList_.begin(), objectList_.end(), &o), objectList_.end()); 
    } 

但是在IronMensan的答覆中提到,更好的辦法是在你的情況下使用std::list::remove(),因爲它是對操作進行了優化清單上並擺脫了多階段拆除。

1

你必須同時使用removeerase因爲remove是不會告訴你的容器,它的已經元素取出(它仍然認爲它包含4個對象,所以在結尾用怪異結束)。

void removeNamedType(NamedType& o) 
{ 
    objectList_.erase(
     std::remove(objectList_.begin(), objectList_.end(), &o), 
     objectList_.end()); 
}