1

I wrote this simple test program. But i can't understand what happens here. Because there is a strange thing in the output:

std::list<std::pair<double,double>> l;
l.push_back({0.3,0.9});
l.push_back({-0.3,0.5});
l.push_back({0.3,0.7});
l.push_back({1.2,1.83});   


for(auto it=l.begin(); it!=l.end(); ++it){
  double lx= it->first + 0.01;
  double ly= it->second + 0.01;

  it->first = lx;
  it->second = ly;

  if(lx < 0.0 || lx > 1.0 || ly < 0.0 || ly > 1.0){
    it = l.erase(it);
 }

If i print the list, i get:

0.32, 0.92
0.31, 0.71

Why does the iterator goes back to the first element (twice +0.1) ?

Suslik
  • 929
  • 8
  • 28
  • 1
    The `==0` in the if is superfluous, in fact the whole if is useless because the `it != end()` will take care of that. And I'm not sure why you said the first element is there twice? It looks like youre removing elements at position 1 and 3 and therefore printing elements 0 and 2. – Borgleader Dec 01 '16 at 18:26
  • Thanks for the answer. Yes it prints Element 0 and 2, but it adds 0.1 twice at the first element. I can't understand why: it should be (0.31, 0.91) and (0.31,0.71) – Suslik Dec 01 '16 at 18:29
  • Just as an aside, a typical pattern for doing this is the *erase-remove idiom* with `l.erase(std::remove_if(...), l.end())`. – sjrowlinson Dec 01 '16 at 18:33
  • @arch under the standard, modifying while `remove`ing is illegal. Annoying, but true. – Yakk - Adam Nevraumont Dec 01 '16 at 18:39
  • see: http://stackoverflow.com/a/263958/14065 – Martin York Dec 01 '16 at 18:45

1 Answers1

7
it=list.erase(it);

This erases the element at it. It then returns the iterator location after the erased element was.

When your for loop finishes an iteration, it advances it, via ++ then checks if it equals end().

So your loop both skips the element after each one erased. Not good. And if it erases the last element it proceeds to advsnce the end iterator, which is illegal.

Remove ++it from the for loop header. At the bottom of the loop, either advance it or erase at it, not both nor neither.

The strange printing behaviour is due to UB. You increment data at location 0. You increment data at location 1, then delete it. You skip location 2. You increment data at location 3, then delete it. You advance past the end iterator (undefined behaviour). Then random stuff happens that just happens to increment data location 0 and 2 again. As a guess, ++ on the end iterator happens to loop back to the first element in your particular case (this is not guaranteed at all, but with UB anything can happen). The second loop then runs as normal, incrementing the data at the two elements and deleting nothing.

Yakk - Adam Nevraumont
  • 262,606
  • 27
  • 330
  • 524