有这样的结构:
struct A {
struct B {
int a = 21;
int b;
int c = 22;
int d;
int e = 23;
};
B b1 = { 11, 12 };
B b2 = { 11, 12, 13 };
int x;
};
宣布:
A a = { { 1, 2, 3, 4 }, { 1 }, 5 };
根据Clang(3.8.0)和GCC(5.4.0),这些是8种可能组合的值(a.b1.e和a.b2.a是重复的情况),关于初始位置值取自(或不),:
a.b1.a = 1 // 111
a.b1.b = 2 // 110
a.b1.c = 3 // 101
a.b1.d = 4 // 100
a.b2.b = 0 // 010 // Why not 12 instead of 0? -> Explained in N3605
a.b2.c = 22 // 011 // Why not 0 instead of 22 ? Why not 13 ?
a.b2.d = 0 // 000
a.b2.e = 23 // 001 // Why not 0 instead of 23 ?
考虑到N3605和C ++ 14标准(ISO / IEC 14882:2014)中的示例,第8.5.1节,第7段:
如果列表中的 initializer-clauses 少于聚合中的成员,那么未显式初始化的每个成员都应从其 brace-or-equal-initializer <初始化< / em>或者,如果没有 brace-or-equal-initializer ,则从空的初始化列表(8.5.4)开始。
我认为案例010是正确的。那么,为什么情况011(a.b2.c)和001(a.b2.e)也不等于零?情况010为零,因为a.b2&#34;确实有一个初始化器&#34;因此&#34;非静态数据成员初始化器被忽略&#34; (N3605再次)。为什么不忽略默认成员初始值设定项?
事实上,阅读C ++ 14标准引用它对我来说更有意义的情况是010将是12(它是零)并且情况011和001将是零(实际上是它们)。所以我不明白为什么a.b2有时被认为是&#34;有一个初始化器&#34;有时则不是。
答案 0 :(得分:6)
您使用其所有成员的初始值设定项a
声明:b1
,b2
和x
。这意味着我们构建好像
a.b1 = B{ 1, 2, 3, 4 };
a.b2 = B{ 1 };
a.x = 5;
B
的定义表明B{ 1, 2, 3, 4 }
表示B{ 1, 2, 3, 4, 23 }
,而B{ 1 }
表示B{ 1, 0, 22, 0, 23 }
。这就是你得到的结果。
如果你写过
A a = { { 1, 2, 3, 4 }, };
然后a.b2
将使用其默认值{11,12}进行初始化:
a.b1 = B{ 1, 2, 3, 4 };
a.b2 = B{ 11, 12 };
a.x = {};
在{ 1 }
&#之前很久,将示例中的{ 11, 12 }
和B
这些大括号表达式视为完全构造的A
对象可能会有所帮助39; s构造函数甚至看到它们。
答案 1 :(得分:2)
在此示例中,{1, 2, 3, 4}
是B b1
的初始值设定项。编译器已经有一个初始化器,所以现在它不再看{ 11, 12 }
了。