Я знаю, что поведение компиляторов не может ничего доказать, но я подумал, что было бы интересно проверить, что даст внутреннее представление компилятора (все же немного более высокий уровень, чем проверка сборки).
Я использовал онлайн-демонстрацию Clang / LLVM с этим кодом:
#include <stdio.h>
#include <stdlib.h>
struct X
{
X const& f(int i) const
{
printf("%d\n", i);
return *this;
}
};
int main(int argc, char **argv) {
int i = 0;
X x;
x.f(++i).f(++i).f(++i); // line 16
}
И скомпилированный со стандартными оптимизациями (в режиме C ++), он дал:
/ tmp / webcompile / _13371_0.cc: в функции 'int main (int, char **)':
/tmp/webcompile/_13371_0.cc:16: предупреждение: операция над 'i' может быть неопределенной
что мне показалось интересным (предупредил ли об этом какой-либо другой компилятор? Comeau онлайн не сделал)
Помимо этого, он также создал следующее промежуточное представление (прокрутка вправо):
@.str = private constant [4 x i8] c"%d\0A\00", align 1 ; <[4 x i8]*> [#uses=1]
define i32 @main(i32 %argc, i8** nocapture %argv) nounwind {
entry:
%0 = tail call i32 (i8*, ...)* @printf(i8* noalias getelementptr inbounds ([4 x i8]* @.str, i64 0, i64 0), i32 3) nounwind ; <i32> [#uses=0]
^^^^^
%1 = tail call i32 (i8*, ...)* @printf(i8* noalias getelementptr inbounds ([4 x i8]* @.str, i64 0, i64 0), i32 3) nounwind ; <i32> [#uses=0]
^^^^^
%2 = tail call i32 (i8*, ...)* @printf(i8* noalias getelementptr inbounds ([4 x i8]* @.str, i64 0, i64 0), i32 3) nounwind ; <i32> [#uses=0]
^^^^^
ret i32 0
}
Очевидно, Clang ведет себя так же, как gcc 4.x.x, и сначала оценивает все аргументы перед выполнением любого вызова функции.