为什么我可以从{}初始化常规数组,而不是std :: array

Alw*_*ing 10 c++ compiler-warnings aggregate-initialization c++11 g++4.8

这有效:

int arr[10] = {};
Run Code Online (Sandbox Code Playgroud)

所有元素arr都被初始化为零.

为什么这不起作用:

std::array<int, 10> arr({}); 
Run Code Online (Sandbox Code Playgroud)

我从g ++(版本4.8.2)收到以下警告:

警告:缺少成员'std :: array <int,10ul> :: _ M_elems'的初始值设定项

Sha*_*our 12

有两个问题,一个是风格和警告问题.

尽管可能并不明显,但聚合初始化正在临时进行,然后将其用作复制构造函数的参数.这种初始化的惯用程度越大,如下:

std::array<int, 10> arr = {}; 
Run Code Online (Sandbox Code Playgroud)

虽然这仍然留下了警告.

该警告由gcc bug报告涵盖: - -Wmissing-field-initializers放宽请求,其中一条评论说:

[...]当然,说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};
Run Code Online (Sandbox Code Playgroud)

这不应该因为早先评论中提到的原因而发出警告.

后续评论说:

我关于零初始化的陈述是不准确的(谢谢),但一般的观点仍然存在:在C中你必须写'= {0}',因为该语言不支持空括号初始化器(你得到一个警告 - -pedantic ); 在C++中,您可以编写'= {}'或'T foo = T();',但您不需要专门编写'= {0}'.

最新版本的gcc在这种情况下不会产生此警告,请参阅它与gcc 5.1一起使用.

我们可以在thead中的Clang Developers列表中看到这个主题:-Wmissing-field-initializers.

作为参考,草案C++ 11标准部分8.5.1 [dcl.init.aggr]说:

如果列表中的initializer-clause少于聚合中的成员,则未显式初始化的每个成员都应从空的初始化列表(8.5.4)初始化.[例如:

struct S { int a; const char* b; int c; };
S ss = { 1, "asdf" };
Run Code Online (Sandbox Code Playgroud)

使用"asdf"初始化ss.a,使用"asdf"初始化ss.b,使用int()形式的表达式的值初始化ss.c,即0.-末端示例

因此这是有效的C++,尽管如上所述使用的{}是无效的C99.有人可能会说它只是一个警告,但这似乎是惯用的C++ {}用于聚合初始化,如果我们-Werror用于将警告变成错误,则会出现问题.


AnT*_*AnT 5

首先,您可以({})初始化程序与std::array对象一起使用,但在语义上代表使用临时值初始化std::array对象的复制构造函数进行直接初始化,即它等效于

std::array<int, 10> arr(std::array<int, 10>{}); 
Run Code Online (Sandbox Code Playgroud)

它实际上应该编译.

其次,({})当你可以做的时候,你真的不需要走的路

std::array<int, 10> arr = {};
Run Code Online (Sandbox Code Playgroud)

要么

std::array<int, 10> arr{};
Run Code Online (Sandbox Code Playgroud)

这两个中的第一个在语法上与你的最相似int arr[10] = {};,这让我想知道为什么你最初没有尝试它.您为什么决定使用({})而不是= {}在构建语法std::array版本时使用= {}