Is the following perfectly defined:
int x = 42, y = x;
i.e. strictly equivalent to:
int x = 42;
int y = x;
<
This question came up in comp.lang.c++.moderated a long time ago under the topic init-declarator-list analysis order and the conclusion there was Yes
.
Although I see the full-expression argument but I do not see the order of evaluation argument. So I think this is unspecified.
The relevant part of the question is:
In this declaration and definition:
int a = 2, b = a;
Is it guaranteed that b will always be initialized as 2 ? If yes, then can we say that a = 2 is always analysed(or evaluated?) before b = a ?
and the relevant part of the answer is:
Yes. Strictly stated, the observable behavior of the program must be as if all of the side effects of the 'a = 2' part of the declaration took place before the evaluation of the 'b = a' part starts. (In practice, of course, in this simple example, a compiler could assign 2 to both a and b in any order, or even in parallel, because doing so would result in the same observable behavior.)
and further down:
In this particular case, however, it does separate the declarator list into separate declarators; each declarator contains a complete expression, and the declarators are evaluated in order.
Update
What makes each init-declator a full expression is subtle but as far as I can tell follows the same logic I used in Are multiple mutations of the same variable within initializer lists undefined behavior pre C++11. In this case we start from the grammar defined in ection 8:
init-declarator-list:
init-declarator
init-declarator-list , init-declarator
init-declarator:
declarator initializeropt
The next point of focus is the initializer grammar which is covered in section 8.5
:
initializer:
brace-or-equal-initializer
( expression-list )
brace-or-equal-initializer:
= initializer-clause
braced-init-list
initializer-clause:
assignment-expression
braced-init-list
In both cases we have = initializer-clause which bring us to assignment-expression which if we follow the grammar in section 5 bring us back to primary-expression which can give us either a literal or id-expression.
So we do indeed have full-expressions separated by a grammatical comma so we have:
int x = 42, y = x;
^ ^
| end full-expression
end full-expression
and according to section 1.9
paragraph 14 we see that:
Every value computation and side effect associated with a full-expression is sequenced before every value computation and side effect associated with the next full-expression to be evaluated.8.
As for the order of evaluation, I think this is not specified, the same logic that applies to defect report 430 for initializer lists would seem to apply here as well. In C++11 the language for initializer lists was fixed with the following addition in section 8.5.4
:
Within the initializer-list of a braced-init-list, the initializer-clauses, including any that result from pack expansions (14.5.3), are evaluated in the order in which they appear. [...]
there is no such equivalent for initializer.