int a = 3, b = 3, c = 2;
a = a++; //a gets incremented to four but then set back to 3
b = ++b; //b gets incremented to four and then pointlessly set to itself
++c = ++c; //now, I agree that this is undefined
Why do I get a == 4? (with he compiler I used all three went to four) Surely it doesn't assign the old value of a to itself and THEN perform the increment?
Yes, it does! the postfix form increments after the whole calculation is preformed! that is ("?somehow?") achieved by doing stuff after returning, I guess.
Because i++ must make a copy, it is less efficient. However, the compiler will probably optimize out the copy where it is without consequence to the program. Many people have just engrained the usage of i++ for things like loops even though the purpose of i++ over ++i, is for use when you need to increment while evaluating at the original value. The optimization of the compiler will fix it for you anyways, essentially replacing everywhere you used i++ unnecessarily, with ++i.
Not sure how that relates, but I have always used ++i unless i++ was more suitable, like you said. Thanks, I'm starting to understand now - optimizations and undefined behavior are creepy.
intoperator++(int)
{
int copy = *this; //First the copy is made
++*this; //now the increment is done
return copy; //returning the copy, which was made before this was incremented... nothing magical hehe.
}
LB: In your example you just omit the copy. Pretty easy huh?
@LB your a = a++;, the v[i] = i++; that started this thread, and other expressions that are undefined because of sequencing rules are only undefined if the variables involved are scalar (scalars include arithmetic types, which include integral types, which include your int a and (I assume) size_t i)
Once you are incrementing an object of class type, where operators are actual function calls, there is no more undefined behavior, although there may be plenty of unspecified behavior.
The situation with var = var++ is extremely straightforward. The two evaluations (assignment and post-fix increment) are unsequenced.
If two evaluations X and Y are unsequenced, X may be evaluated before Y; Y may be evaluated before X; or the evaluations of X and Y may overlap.
With the expression function_one() + function_two(), the two evaluations are indeterminately sequenced. function_one() may be evaluated before function_two() or function_two() may be evaluated before function_one(). But the evaluations of the sub-expressions will never overlap.
In function(++var), the evaluation of ++var is sequenced before the evaluation of function().
@JLBorges it is simple for simple cases, but I don't think people realized that for a vector v, v[i] = i++; is also undefined because the prvalue evaluation of subexpression i on the left and the side effect evaluation of the subexpression i++ on the right are unsequenced.
> it is simple for simple cases, but I don't think people realized that for a vector v, v[i] = i++; is also undefined
Yes; but the compiler can draw the programmers attention to a potential problem. Programmers who habitually enable all compiler diagnostics, and pay attention to them, would make fewer mistakes.
1 2 3
std::vector<int> seq = { 0, 1, 2, 3, 4 } ;
int i = 1 ;
seq[i] = i++ ; // warning: operation on 'i' may be undefined [-Wsequence-point]