0

I had a typo in code recently, that was causing an infinite loop in some cases (but not in all environments, it seems).
It looked like this:

for (std::vector<myString>::iterator iter = myVector.begin(); iter != myVector.end(); ++iter = iter)
{
   ...
}

The typo is the assignment of the iterator to itself. Removing it fixes the issues.

I am wondering what exactly happens during the statement ++iter = iter?
I thought that according to operator precedence, iterator should first be incremented, then assigned to self, but I seem to be missing some steps (otherwise there would not be infinite loops).
My feeling is that it also involves dereferencing of the variable, but I am not sure to completely understand what was happening with this bug.
Also, why did it seem to not cause infinite loops on some platforms?

wip
  • 2,090
  • 3
  • 27
  • 44

1 Answers1

3

according to operator precedence, iterator should first be incremented, then assigned to self

Operator precedence does not determine evaluation order.

If the expression d = (a+b)*c, a, b, c and d can be evaluated in any order. a+b has to be evaluated after a and b, (a+b)*c after both a+b and c, and the result of the assignment after both d and the result of the multiplication, but that's about it.

The same used to be the case with the assignment.

The left-hand side and the right-hand side of the assignment previously could be evaluated in any order. In particular, the following order could be realised:

  • iter is evaluated, resulting in a value we call temp
  • ++iter is evaluated (this doesn't affect temp)
    • this results in incrementing of iter, and the value is the newly-incremented iter rvalue
  • temp is assigned to the iter rvalue evaluated above
  • the net result is iter being unchanged

Another evaluation order also used to be possible.

  • ++iter is evaluated
    • this results in incrementing of iter, and the value is the newly-incremented iter rvalue
  • iter (the right hand side of the assignment) is evaluated again
    • the result is the newly-incremented iter converted to lvalue
  • the assignment takes place, leaving iter incremented as expected.

However C++17 has changed this. Assignment is now evaluated strictly from right to left. This means the first evaluation order is now guaranteed, and the second one is not allowed.

n. 'pronouns' m.
  • 95,181
  • 13
  • 111
  • 206
  • Thank you for the explanations. Maybe adding pseudo-code illustrating the two evaluation orders that used to be possible, would be useful? – wip Nov 20 '18 at 01:02