2013-01-21 98 views
0

可能重複:
How to filter items from a std::map?
std::list::erase not working刪除/從STD擦除::列表

我有一些無聊的問題關於刪除,擦除的std ::名單。

我已經定義的類爲:

class CBase 
{ 
public: 
    CBase(int i): m(i) 
    {}; 

    int m; 
}; 

然後,我將其設置爲:

list<CBase> ml; 
CBase b1(1); 
CBase b2(2); 
CBase b3(3); 
CBase b4(4); 
ml.push_back(b1); 
ml.push_back(b2); 
ml.push_back(b3); 
ml.push_back(b4); 

我可以擦除其具有m == 2由項;

for (list<CBase>::iterator it=ml.begin(); it!=ml.end(); ++it) 
{ 
    if (it->m == 2) 
    { 
     ml.erase(it--); 
    } 
} 
    // show what we have now: 
for (list<CBase>::iterator it=ml.begin(); it!=ml.end(); it++) 
{ 
    cout << it->m; 
} 

但是,如果我做的:

for (list<CBase>::iterator it=ml.begin(); it!=ml.end(); it++) 
{ 
    if (it->m == 2) 
    { 
     ml.erase(it); 
     it--; 
    } 
} 

會有例外。爲什麼是這樣?

如果我想刪除B3,

ml.remove(B3);

不會編譯。我在網上找到的所有示例使用list<int>,並且如果mylist is list<int>調用mylist.remove(3)沒有問題。我怎樣才能使它工作?

+0

DUP:http://stackoverflow.com/questions/12666869/stdlisterase-not-working – Csq

+0

的STL具有隻是反正這樣的情況下是非常有效的算法:HTTP ://en.cppreference.com/w/cpp/algorithm/remove – SirDarius

+1

@SirDarius:'std :: list'有它自己的remove/remove_if函數,因爲它們重新排列鏈接而不是移動元素,所以它更有效。 –

回答

1

因爲擦除使迭代器無效。它可能不再使用,包括遞減運算符。

編輯:至於刪除,它將刪除值等於您指定的值的元素。 std::list使用operator==進行比較,除非您定義了它,編譯將失敗。只需定義運營商,並且應該沒問題。

+0

在某些情況下,可能不是這個,爲一個「operator ==」定義一個類沒有意義,或者它沒有明確正確的實現,並且不應該僅僅爲了在對象被放置在容器中時能夠與某些算法一起使用而完成。如果是這樣的話,你可以使用'std :: list <> :: remove_if',傳遞一個合適的謂詞。 –

+0

嗯,我只是編譯他的代碼,並觀察編譯器錯誤。我認爲在stl中使用'operator <'進行比較是標準的,但似乎並非如此。 –

+0

別擔心,我並不是說你的建議不是個好主意。我只是提供了一些額外的信息,以便當他想在另一個可能使用'operator =='不適用的類上使用這種技術時,他沒有被卡住。 –

1

erase之後,您傳遞給它的迭代器將無效。

現在,使用

ml.erase(it--); 

你傳遞一個erase副本迭代,移動您的副本向後,使之不再是指在列表中的同一個地方。
--發生的erase複製已經準備,但erase實際被調用。
調用之後,你的迭代器仍然有效,它是你刪除的元素之前的一個位置。

但是,如果你

ml.erase(it); 
it--; 

it仍試圖調用後引用刪除的元素,當你嘗試,因爲它是無效的修改,你會得到一個異常。

2

您正在取消引用指向擦除元素的迭代器。使用erase()成員函數的返回值:

it = ml.erase(it); 
// 'it' now points at first element after the last deleted element