Interdependent initialization with commas?

后端 未结 2 1380
谎友^
谎友^ 2021-01-02 03:44

Is the following perfectly defined:

int x = 42, y = x;

i.e. strictly equivalent to:

int x = 42;
int y = x;
<
2条回答
  •  天涯浪人
    2021-01-02 03:48

    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.

提交回复
热议问题