简体   繁体   中英

Partial Aggregate Initialization and Non-static Data Member Initializer

struct Point {
  int x = 0;
  int y = 10;
};

Point p = {1,};
p.x == 1;  // true
p.y == 10; // is this true?

According to the standard missing elements in initializer list are value initialized, so y should be int() or 0 , but it doesn't seem to say what happen in the situation of Non-static Data Member Initializer.

Edit: According to the answer, apparently this is invalid c++11, I would like to know the situation in c++1y.

C++98, C++03

Non-static data member initialisers (NSDMIs) do not exist; the question is inapplicable.


C++11

Well, first of all, this initialisation is invalid because your type is not an aggregate:

[C++11: 8.5.1/1]: An aggregate is an array or a class (Clause 9) with user-provided constructors (12.1), no brace-or-equal-initializers for non-static data members (9.2), no private or protected non-static data members (Clause 11), no base classes (Clause 10), and no virtual functions (10.3).

So, aggregate initialisation can't be performed here; a constructor taking an std::initializer_list would be your only way to use that initialisation syntax ( [C++11: 8.5.4/3] ), but you don't have one of those either.

Consequently, the entire premise of the question is flawed: it is not possible to get yourself into this state.


C++1y

In the upcoming version of the standard, the definition of aggregates has been relaxed to allow your type to be deemed an aggregate (as long as both of those members stay public !):

[n3936: 8.5.1/1] An aggregate is an array or a class (Clause 9) with no user-provided constructors (12.1), no private or protected non-static data members (Clause 11), no base classes (Clause 10), and no virtual functions (10.3).

Following on from this, there's a rule that guarantees the result you're looking for:

[n3936: 8.5.1/7] : If there are fewer initializer-clauses in the list than there are members in the aggregate, then each member not explicitly initialized shall be initialized from its brace-or-equal-initializer or, if there is no brace-or-equal-initializer , from an empty initializer list (8.5.4). [ Example:

 struct S { int a; const char* b; int c; int d = b[a]; }; S ss = { 1, "asdf" }; 

initializes ss.a with 1 , ss.b with "asdf" , ss.c with the value of an expression of the form int{} (that is, 0 ), and ss.d with the value of ss.b[ss.a] (that is, 's' ), and in

 struct X { int i, j, k = 42; }; X a[] = { 1, 2, 3, 4, 5, 6 }; X b[2] = { { 1, 2, 3 }, { 4, 5, 6 } }; 

a and b have the same value —end example ]

(Answer valid in C++1y, only !)

According to paragraph #7 of section "8.5.1 Aggregates" (Working Draft N3691 Date: 2013-05-16)

7 If there are fewer initializer-clauses in the list than there are members in the aggregate, then each member not explicitly initialized shall be initialized from its brace-or-equal-initializer or, if there is no brace-or-equalinitializer, from an empty initializer list (8.5.4).

And below the quote there is an example

[ Example: struct S { int a; const char* b; int c; int d = b[a]; }; 
S  ss = { 1, "asdf" };
 initializes ss.a with 1, ss.b with "asdf", ss.c
with the value of an expression of the form int{} (that is, 0), and
ss.d with the value of ss.b[ss.a] (that is, ’s’),

So in your example py will be initialized by 10.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM