可能重复:
How to filter items from a std::map?
std::list::erase not working
我对std :: list中的删除,擦除有一些愚蠢的问题。
我有一个定义为:
的类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 by;
的项目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.remove(3)
调用mylist is list<int>
则没有问题。我怎样才能使它发挥作用?
答案 0 :(得分:2)
您正在取消引用指向已擦除元素的迭代器。使用erase()
成员函数的返回值:
it = ml.erase(it);
// 'it' now points at first element after the last deleted element
答案 1 :(得分:1)
因为erase使迭代器无效。它可能不再被使用,包括减量运算符。
编辑:对于删除,它会删除值等于您指定的元素。 std::list
使用operator==
进行比较,除非您已定义,否则编译将失败。只需定义操作符即可。
答案 2 :(得分:1)
在erase
之后,传递给它的迭代器将无效。
现在,使用
ml.erase(it--);
您正在通过erase
您的迭代器的副本,和向后移动您的副本,因此它不再引用列表中的相同位置
{<1}}在 --
的副本准备好之后发生,但 erase
之前的实际上已被调用。
调用之后,您的迭代器仍然有效,并且它是您删除的元素之前的一个位置。
但如果你这样做
erase
ml.erase(it);
it--;
仍在尝试在调用后引用已删除的元素,并且当您尝试修改它时会出现异常,因为它无效。