1

根据valgrind的说法,这个问题是由下面的代码引起的。我想删除列表中的元素,该元素包含与ref相同的整数值。

while(itr1!=list1.end())
{
 if(itr1->num==ref)
 {
  list1.erase(itr1);
 }
 else
 {itr1++;}
}

list1 是一个 STL 列表,列表元素的类型是 NODE,它是一个结构体。num 是 NODE 中的整数元素之一。itr1 是 list1 的迭代器。ref 是一个整数值。


但是在我用下面的代码替换后,它是正确的

for(;itr1!=list1.end();itr1++)
{
 if(itr1->num==ref)
 {
  list1.erase(itr1);
  itr1--;
 }
}

我真的看不出这两个片段之间的区别。

我不知道您是否可以找出代码不完整的问题。如果您需要,我可以发布所有程序。谢谢!

4

3 回答 3

4

erase被移除元素的迭代器失效之后。第二个代码由于运气而起作用,尽管这是未定义的行为并且代码应该被认为是错误的。

于 2013-06-22T15:57:48.323 回答
2

问题是您在擦除元素后没有退出循环。指向已擦除元素的迭代器无效

while(itr1!=list1.end())
{
 if(itr1->num==ref)
 {
  list1.erase(itr1);
  break;
 }
 else
 {itr1++;}
}

您是否考虑过使用remove_if

如果您知道列表中只有一个具有该值的元素(remove_if 搜索所有出现),则效率可能会降低。

于 2013-06-22T15:57:34.900 回答
-1

迭代器实际上是变相的指针。当您通过迭代器擦除时,该迭代器变得无效;它类似于做 a deleteor free()。解决方案与经典 C 代码中的相同:

// Classic C code for removing all nodes matching 
// key_to_delete from doubly-linked list:
while (itr != list->null_node)
{
   node *next = itr->next; // Calculate next node now, while itr is valid!

   if (itr->data == key_to_delete) {
      itr->prev->next = itr->next;
      itr->next->prev = itr->prev;
      list_node_free(itr);
   }

   itr = next; // Advance to previously calculated next node
}

C++ 中带有列表容器的相同概念:

while (itr1 != list1.end())
{
   std::list<whatever>::iterator next = itr1;  // calculate next iterator now
   next++;                                     // while itr1 is valid

   if (itr1->num == ref)
   {
     list1.erase(itr1);
   }

   itr1 = next;
}

对列表迭代器的erase操作只会使该迭代器(以及它的所有副本)无效。它不会使指向列表其他部分的迭代器无效。这就是为什么值next可以在擦除后仍然存在并且可以使用的原因。

于 2013-06-22T19:11:25.070 回答