问题
I use the following in my C++ code:
int a = 0, b = a;
I would like to know if this behaviour is reliable and well defined (left to right order of name declaration) and that my code will not break with other compilers with an undeclared name error.
If not reliable, I would break the statement:
int a = 0;
int b = a;
Thank you.
回答1:
I believe the answer is no.
It is subject to core active issue 1342 which says:
It is not clear what, if anything, in the existing specification requires that the initialization of multiple init-declarators within a single declaration be performed in declaration order.
We have non-normative note in [dcl.decl]p3 which says:
...[ Note: A declaration with several declarators is usually equivalent to the corresponding sequence of declarations each with a single declarator. That is
T D1, D2, ... Dn;
is usually equivalent to
T D1; T D2; ... T Dn;
...
but it is non-normative and it does not cover the initialization case at all and as far as I can tell no normative wording says the same thing.
Although the standard does cover the scope of names in [basic.scope.pdecl]p1 which says:
The point of declaration for a name is immediately after its complete declarator and before its initializer (if any), except as noted below. [ Example:
unsigned char x = 12; { unsigned char x = x; }
Here the second x is initialized with its own (indeterminate) value. — end example ]
回答2:
The fact that you thought to ask this question suggests that the style is not great. Even though the one-line version is almost guaranteed† to work, I would still go with the two-line approach for the greater clarity to human readers.
† I initially said it was guaranteed, but I will step back from that. After reviewing the relevant portion of the spec, I can see how language lawyers would complain that this guarantee is not explicitly stated. (As Shafik Yaghmour points out, core active issue 1342 notes the lack of an explicit guarantee, albeit with phrasing that suggests that such a guarantee should be present.)
I will step back only to "almost guaranteed", though, as it is strongly implied by "Each init-declarator in a declaration is analyzed separately as if it was in a declaration by itself.". That is, the analysis of int a = 0, b = a;
has two parts: one where a variable named a
is initialized to 0
, and one where a variable named b
is initialized to the value of a
. If you are truly keeping these parts separate, then the first part would have to finish before the second part begins (otherwise they are not as if each was in a declaration by itself), so a
would have the value 0
before b
is initialized. I accept that this might be not definite enough for the language lawyers, but it should be good enough for a compiler's bug report if there is a compiler for which that line does not work as intended.
My apologies for not looking up the spec earlier. The "language-lawyer" tag was not present when I initially answered.
回答3:
A declaration statement that defines multiple variables separated by comma is exactly equivalent to multiple declaration statements that defines a single variable in the same order because the scope of a variable begins just after it's name, but there are (at least) two exceptions:
1) When a variable declaration hides a type with the same name, as in:
struct S {};
S S, T;
Is different from
struct S {};
S S;
S T; //error: S is a variable name
But
struct S {};
S S, T{S};
Is equivalent to
struct S{};
S S;
struct S T{S};
2) When using the auto
and decltype(auto)
specifiers:
auto i{0}, j{i}, k{2.0}; // error: deduction for auto fails, double or int?
Is different from
auto i{0};
auto j{i};
auto k{2.0};
In any case, evaluation order is always from left to right.
来源:https://stackoverflow.com/questions/53698162/c-order-of-declaration-in-multi-variable-declaration-line