2013-01-21 71 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