7

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

我可能做错了,但无论如何都会感谢帮助。谢谢。

4

4 回答 4

24

这里的核心问题是您在it调用迭代器值之后erase使用它。该erase方法使迭代器无效,因此继续使用它会导致不良行为。相反,您希望erase在擦除值之后使用返回来获取下一个有效迭代器。

it = newList.begin();
for (int i = 0; i < 5; i++) {
  it = newList.erase(it);
}

包括一个检查newList.end()来说明list.

it = newList.begin();
for (int i = 0; i < 5 && it != newList.end(); i++) {
  it = newList.erase(it);
}

正如蒂姆所指出的,这里有一个很好的参考erase

于 2011-02-28T17:58:31.090 回答
3

当您擦除 position 处的元素时it,迭代器it将失效 - 它指向您刚刚释放的一块内存。

erase(it)函数返回另一个迭代器,指向列表的下一个元素。用那个!

于 2011-02-28T18:00:01.260 回答
2

当您erase()在循环中时,您正在使您的迭代器无效。做这样的事情来代替你的擦除循环会更简单:

list_item_t::iterator endIter = newlist.begin();
std::advance(endIter, 5);
newList.erase(newlist.begin(), endIter);

您可能还对擦除删除习语感兴趣。

于 2011-02-28T18:00:48.790 回答
2

我这样做:

for(list<type>::iterator i = list.begin(); i != list.end(); i++)
{
     if(shouldErase)
     { 
        i = list.erase(i);
        i--;
     }
}

编辑是因为我是一个显然无法阅读的傻瓜,哈哈。

于 2012-04-28T15:50:39.103 回答