这有效:
int arr[10] = {};
arr
的所有元素都被初始化为零。
为什么这不起作用:
std::array<int, 10> arr({});
我从g ++(版本4.8.2)收到以下警告:
警告:缺少成员'std :: array&lt; int,10ul&gt; :: _ M_elems'
的初始值设定项
答案 0 :(得分:12)
有两个问题,一个是风格和警告问题。
虽然可能不是很明显,但是聚合初始化发生在临时,然后被用作复制构造函数的参数。这种初始化的惯用程度如下:
std::array<int, 10> arr = {};
虽然这仍然留下警告。
警告由gcc bug report: - -Wmissing-field-initializers relaxation request 涵盖,其中一条评论说:
[...]当然,说MyType x = {}的C ++语法;应该得到支持, 如下所示:
http://en.cppreference.com/w/cpp/language/aggregate_initialization
例如:
struct S { int a; float b; std::string str; }; S s = {}; // identical to S s = {0, 0.0, std::string};
由于前面评论中所述的原因,不应该发出警告。
后续评论说:
我关于零初始化的陈述是不准确的(谢谢),但是 一般的观点仍然存在:在C中你必须写&#39; = {0}&#39;以来 语言不支持empty-braces初始化程序(你得到一个 警告与-pedantic);在C ++中,你可以写&#39; = {}&#39;或者&#39; T foo = T();&#39;,但你不需要写&#39; = {0}&#39;具体
最新版本的gcc不会针对此案例see it live working with gcc 5.1生成此警告。
我们可以在thead中的Clang开发人员列表中看到此主题:-Wmissing-field-initializers。
作为参考,草案C ++ 11标准部分8.5.1
[dcl.init.aggr] 表示:
如果列表中的初始化子句数少于 聚合中的成员,然后每个成员未明确初始化 应从空的初始化列表(8.5.4)初始化。 [ 例如:
struct S { int a; const char* b; int c; }; S ss = { 1, "asdf" };
使用1,ss.b和#34; asdf&#34;和ss.c初始化ss.a,其值为 形式为int()的表达式,即0.-end example]
因为这是有效的C ++,尽管使用{}
指出的是无效的C99。有人可能会说它只是一个警告,但这似乎是使用{}
进行聚合初始化的惯用C ++,如果我们使用-Werror
将警告转换为错误,则会出现问题。
答案 1 :(得分:5)
首先,可以使用({})
初始值设定项和std::array
对象,但语义上代表使用临时值初始化{的复制构造函数进行直接初始化{1}}对象,即它相当于
std::array
它实际上应该编译。
其次,当你可以做的时候,你真的不必走std::array<int, 10> arr(std::array<int, 10>{});
方式
({})
或
std::array<int, 10> arr = {};
两者中的第一个在语法上与std::array<int, 10> arr{};
最相似,这让我想知道你为什么一开始就没有尝试过。在构建int arr[10] = {};
语法的({})
版本时,为什么决定使用= {}
而不是std::array
?
答案 2 :(得分:2)
当用-Werror
进行编译时,足够的人已经指出这是一个“问题”,我认为值得一提的是,如果你加倍,问题就会消失:
std::array<int, 10> arr{{}};
在gcc 4.9.2上没有对我发出任何警告。
为了解释它的原因添加一点:我的理解是std :: array实际上是一个以C数组作为唯一成员的类。所以在括号上加倍是有道理的:外括号表示你正在初始化类,然后内括号默认初始化该类的唯一成员。
因为当一个类中只有一个变量时不存在歧义,所以只使用一对{}应该是合理的,但gcc在这里过于迂腐,并发出警告。