Reputation: 499
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
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
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