正如评论中提到的和@sbabbi 所回答的那样,答案在于细节
12.6.2 初始化基和成员 [class.base.init]
在非委托构造函数中,如果给定的非静态数据成员或基类不是由 mem-initializer-id 指定的(包括由于构造函数没有 ctor-initializer 而没有 mem-initializer-list 的情况)并且实体不是抽象类(10.4)的虚拟基类,则
- 如果实体是具有大括号或相等初始化器的非静态数据成员,则实体按照 8.5 中的规定进行初始化;
- 否则,如果实体是匿名联合或变体成员(9.5),则不执行初始化;
- 否则,实体默认初始化
12.6.2 初始化基和成员 [class.base.init]
如果给定的非静态数据成员同时具有大括号或等式初始化器和内存初始化器,则执行内存初始化器指定的初始化,并且非静态数据成员的大括号或等式初始化器是忽略。[示例:给定
struct A {
int i = /∗ some integer expression with side effects ∗/ ;
A(int arg) : i(arg) { }
// ...
};
A(int) 构造函数将简单地将 i 初始化为 arg 的值,并且 i 的大括号或相等初始化器中的副作用不会发生。—结束示例]
所以,如果有非删除构造函数,则忽略大括号或等号初始化器,以构造函数的成员内初始化为准。因此,对于省略了大小的数组成员,表达式变得不正确。§12.6.2,第 9 项,在我们指定如果 mem-initialization 由构造函数执行时省略 r-value 初始化表达式的地方更加明确。
此外,谷歌小组讨论了 C++ 中的另一种不一致的行为,进一步阐述并使其更加清晰。它扩展了这个想法,解释了大括号或等于初始化器是成员内初始化的一种美化方式,用于成员的成员内初始化不存在的情况。举个例子
struct Foo {
int i[5] ={1,2,3,4,5};
int j;
Foo(): j(0) {};
}
相当于
struct Foo {
int i[5];
int j;
Foo(): j(0), i{1,2,3,4,5} {};
}
但是现在我们看到,如果省略了数组大小,则表达式将是格式错误的。
但是话说回来,当成员没有被成员内构造函数初始化但目前为了统一起见,标准像许多其他东西一样,不支持此功能的情况下,编译器本可以支持该功能。