我正在尝试使用erase
和列表迭代器从C ++链接列表中删除项目:
#include <iostream>
#include <string>
#include <list>
class Item
{
public:
Item() {}
~Item() {}
};
typedef std::list<Item> list_item_t;
int main(int argc, const char *argv[])
{
// create a list and add items
list_item_t newlist;
for ( int i = 0 ; i < 10 ; ++i )
{
Item temp;
newlist.push_back(temp);
std::cout << "added item #" << i << std::endl;
}
// delete some items
int count = 0;
list_item_t::iterator it;
for ( it = newlist.begin(); count < 5 ; ++it )
{
std::cout << "round #" << count << std::endl;
newlist.erase( it );
++count;
}
return 0;
}
我得到了这个输出,似乎无法追查原因:
added item #0
added item #1
added item #2
added item #3
added item #4
added item #5
added item #6
added item #7
added item #8
added item #9
round #0
round #1
Segmentation fault
我可能做错了,但无论如何都会感激帮助。感谢。
答案 0 :(得分:23)
这里的核心问题是,在您调用it
之后,您正在使用迭代器值erase
。 erase
方法使迭代器无效,因此继续使用它会导致不良行为。相反,您希望使用erase
的返回值来获取擦除值之后的下一个有效迭代器。
it = newList.begin();
for (int i = 0; i < 5; i++) {
it = newList.erase(it);
}
如果newList.end()
中至少包含5个元素,则list
的检查也不会受到影响。
it = newList.begin();
for (int i = 0; i < 5 && it != newList.end(); i++) {
it = newList.erase(it);
}
正如Tim所指出的,这里是erase
答案 1 :(得分:3)
当您擦除位置it
处的元素时,迭代器it
将失效 - 它指向您刚刚释放的一块内存。
erase(it)
函数返回另一个指向列表下一个元素的迭代器。使用那个!
答案 2 :(得分:2)
当你在循环中erase()
时,你的迭代器无效。用这样的东西代替你的擦除循环会更简单:
list_item_t::iterator endIter = newlist.begin();
std::advance(endIter, 5);
newList.erase(newlist.begin(), endIter);
您可能也对erase-remove idiom感兴趣。
答案 3 :(得分:2)
我这样做:
for(list<type>::iterator i = list.begin(); i != list.end(); i++)
{
if(shouldErase)
{
i = list.erase(i);
i--;
}
}
编辑,因为我是一个看不懂的傻瓜大声笑。