18

Consider the following initializations:

/* C, C++ */
int a[] = { f(), g() };
struct { int x, y } foo = { f(), g() };

/* C++ */
struct goo { goo(int x, int y);  };

goo b = { f(), g() };
goo c { f(), g() };    /* C++11 */
goo d ( f(), g() );

Is the order of execution f() and g() in any line specified by C and C++ standards?

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335

4 Answers4

21

In all these two cases

goo b = { f(), g() };
goo c { f(), g() };    /* C++11 */

the order of evaluation is determined from left to right and all side effects shall be applied before the next initializer.

From the C++ STandard

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. That is, every value computation and side effect associated with a given initializer-clause is sequenced before every value computation and side effect associated with any initializer-clause that follows it in the comma-separated list of the initializer-list.

However in C there is other rule

The evaluations of the initialization list expressions are indeterminately sequenced with respect to one another and thus the order in which any side effects occur is unspecified.

ajay
  • 9,402
  • 8
  • 44
  • 71
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
  • Come to think of it, I think all but the last are like this in C++11. – chris Mar 19 '14 at 19:09
  • @Vlad: What about first two lines in C++11? The order isn't determined? –  Mar 19 '14 at 19:18
  • 1
    @Corvus The first expression int a[] = { f(), g() }; satisfies the rule. Take into account that GCC 4,8,2 has a bug. As for the second expression then is shall not be compiled.:) There is no declarator. – Vlad from Moscow Mar 19 '14 at 19:21
  • @Vlad: Sorry for the second expression. I've edit it. –  Mar 19 '14 at 19:32
  • @haccks: What rule makes it determined for `goo d`, which has no braced init list? – Ben Voigt Mar 19 '14 at 20:27
  • @BenVoigt; My apologies. I did't noticed that. – haccks Mar 19 '14 at 20:29
  • what about initializer list in constructor? are they evaluated in order? – SwiftMango Mar 25 '14 at 20:11
  • @texasbruce From C++ Standard: "— Then, non-static data members are initialized in the order they were declared in the class definition (again regardless of the order of the mem-initializers)." – Vlad from Moscow Mar 25 '14 at 21:04
11

Is the order of execution f() and g() in any line specified by C and C++ standards?

In C, No. They can evaluate in any order.

C11 6.7.9 Initialization

The evaluations of the initialization list expressions are indeterminately sequenced with respect to one another and thus the order in which any side effects occur is unspecified,152).

While C++11 says that the order of evaluation is deterministic.

8.5.4:4 List-initialization

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. That is, every value computation and side effect associated with a given initializer-clause is sequenced before every value computation and side effect associated with any initializer-clause that follows it in the comma-separated list of the initializer-list.


152) In particular, the evaluation order need not be the same as the order of subobject initialization.

Community
  • 1
  • 1
haccks
  • 104,019
  • 25
  • 176
  • 264
2

No, in C the order of evaluation of the initializers is unspecified:

(C11, 6.7.9p23) "The evaluations of the initialization list expressions are indeterminately sequenced with respect to one another and thus the order in which any side effects occur is unspecified.152)"

152) In particular, the evaluation order need not be the same as the order of subobject initialization.

In C++ the behavior is different, and the initializers are evaluated in the order in which they appear (C++11, 8.5.4p4).

ouah
  • 142,963
  • 15
  • 272
  • 331
2

In C++11, the relevant part is paragraph 4 of 8.5.4 List-initialization

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. That is, every value computation and side effect associated with a given initializer-clause is sequenced before every value computation and side effect associated with any initializer-clause that follows it in the comma-separated list of the initializer-list. [ Note: This evaluation ordering holds regardless of the semantics of the initialization; for example, it applies when the elements of the initializer-list are interpreted as arguments of a constructor call, even though ordinarily there are no sequencing constraints on the arguments of a call. — end note ]

So the order of evaluation is left-to-right.

However note that unfortunately, due to a bug since at least version 4.7.0, GCC evaluates in the opposite order, right-to-left. So if you get any unexpected results, this may be a reason.

iavr
  • 7,547
  • 1
  • 18
  • 53