I am here discussing "Don’t depend on the order of evaluation of function arguments". Now I think you may worry, what I am talking about because many Developers assumed that the order of the evaluation of function arguments is left to right. Wrong! You have no guarantees!
Reason Because that order is unspecified.
Note C++17 tightens up the rules for the order of evaluation, but the order of evaluation of function arguments is still unspecified.
Now take simple example:
//test.cpp
#include <iostream>
void foo(int a, int b) {
std::cout << "a: " << a << " " << "b: " << b << std::endl;
}
int main() {
int i = 0;
foo(i++, i++); // (1, 0) | (0, 1) | (0, 0)
return 0;
}
If you understand what I am saying why this comment then you actually on the way. If not then get a move to the explanation.
Here is my proof. The output from gcc and clang differs:
- gcc
g++ -std=c++2a -O3 -Wall test.cpp -o test && ./test
test.cpp: In function ‘int main()’:
test.cpp:9:15: warning: operation on ‘i’ may be undefined [-Wsequence-point]
9 | foo(i++, i++); // (1, 0) | (0, 1) | (0, 0)
| ~^~
test.cpp:9:15: warning: operation on ‘i’ may be undefined [-Wsequence-point]
a: 1 b: 0
- clang
clang++ -std=c++2a -O3 -Wall test.cpp -o test && ./test
test.cpp:9:10: warning: multiple unsequenced modifications to 'i' [-Wunsequenced]
foo(i++, i++); // (1, 0) | (0, 1) | (0, 0)
^ ~~
1 warning generated.
a: 0 b: 1
The call will most likely be foo(0, 1) or foo(1, 0), but you don’t know which. Technically, the behavior is undefined. In C++17, this code does not have undefined behavior, but it is still not specified which argument is evaluated first.
I compile in C++20 or give the best possible error in compilation with optimization with a compiler flag.
If you want to learn more about this then follow these links: