Elod
Elod

Reputation: 499

c++ iterator comparison Assertion Failed

I have a list list<x> bar and an array of iterators list<x>::iterator foo[100] initialized all elements with bar.end().

I want to store pointers in foo to some elements in bar while I'm going to erase, insert and push_back elements into bar. For element insertion I have to check if a position in foo is empty or not:

if (foo[my_number] != bar.end())
  //do something 1
else
  //do something 2

I receive an error only in case the foo[my_number] is already pointing to a bar element. The if is true I got this error (if false, no problem):

Debug Assertion Failed!

Program: C:\Windows\system32\MSVCP120D.dll
File: C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\include\list
Line: 289

Expression: list iterators incompatible

I read here that after insertion the bar.end() is not the same as before. However, my code doesn't fail if I push back elements and compare a bar.end and foo[k] = end. But fails to compare bar.end to foo[k] = bar.begin() + p (this bar element exist).

What am I missing? How can I overcome this problem? Should I re-actualize foo after I inserted elements?

Upvotes: 2

Views: 1096

Answers (2)

Marvin Sielenkemper
Marvin Sielenkemper

Reputation: 820

Erasing an element from a std::list invalidates iterators pointing to it (see here). So if you do erase from bar, be sure to remove the corresponding iterators from foo. All other std::list operations are supposed to keep existing iterators valid.

The link you found points to a question about std::vector which behaves differently with regard to iterator invalidation.

Upvotes: 2

marcinj
marcinj

Reputation: 50036

insert or push_back operation in std::list does not invalidate iterators or references. erase invalidates iterators (and references) to the erased elements. The problem is caused by that you use iterator to erased element, after erase (or before), you should update this element iterator also in your array - preferable to end iterator.

The problem is that you should first find it, so before erase you might need to search it. How to you plan to keep synchronized your array and list?

Below is some example what you can and should not do:

  std::list<int> lst;
  std::vector<std::list<int>::iterator> arr;

  // Init arr with end() iterator
  arr.push_back(lst.end());

  // Add new list element
  lst.push_back(0);

  // Remember where it is in arr
  arr[0] = lst.begin();

  // Compare it.
  if ( arr[0] == lst.begin())
  {
    std::cout << "this is OK!\n";
  }

  lst.push_back(0);

  if (arr[0] == lst.begin())
  {
    std::cout << "this is still OK!\n";
  }

  lst.erase(lst.begin());
  //arr[0] = lst.end(); - without this, "list iterators incompatible" is issued by VS below
  if (arr[0] == lst.begin())
  {
    // list iterators incompatible
    std::cout << "This is WRONG!\n";
  }

Upvotes: 2

Related Questions