Take this example code:
int a = 10;
int b = 20;
int c = 30;
int & foo1() {
qDebug() << "foo1" << endl;
return a;
}
int & foo2() {
qDebug() << "foo2" << endl;
return b;
}
int & foo3() {
qDebug() << "foo3" << endl;
return c;
}
int main(void)
{
foo1() = foo2() = foo3() = 7;
}
Since assignment goes right to left, I expected to see foo3
first and foo1
last, but it is the opposite.
Are the rules for such scenarios concretely defined and how? Also, does the compiler differentiate between assignment and other operators and how would that be possible if you are using the =
operator in a different context than initialization? Maybe chain assignment is treated differently from other chaining?
The full expression
foo1() = foo2() = foo3() = 7
can be abstracted with the following tree:
=
/ \
foo1() =
/ \
foo2() =
/ \
foo3() 7
The leaves of that tree can be evaluated in any order. Your compiler is free to choose. Only for calling the assignment operator the expressions hanging on them must be evaluated first. In your case the leaves get evaluated in the order foo1()
, foo2()
and then foo3()
.
The right to left associativity of =
is only seen in the shape of the tree, but not in the order of evaluation. The tree for
std::cout << foo1() << foo2() << foo3()
looks like
<<
/ \
<< foo3()
/ \
<< foo2()
/ \
std::cout foo1()
Again the foo
functions may be evaluated in any order, but the order of evaluations of the operator<<()
is well-defined. There is an interesting post about sequence points which describes the topics very well.