这有效:
int arr[10] = {};
的所有元素的arr
值初始化为零。
为什么这不起作用:
std::array<int, 10> arr({});
我从 g++(4.8.2 版)收到以下警告:
警告:成员 'std::array<int, 10ul>::_M_elems'</p> 缺少初始化程序
这有效:
int arr[10] = {};
的所有元素的arr
值初始化为零。
为什么这不起作用:
std::array<int, 10> arr({});
我从 g++(4.8.2 版)收到以下警告:
警告:成员 'std::array<int, 10ul>::_M_elems'</p> 缺少初始化程序
有两个问题,一个是风格问题和警告问题。
尽管可能并不明显,聚合初始化发生在一个临时对象上,然后用作复制构造函数的参数。更惯用的初始化方法如下:
std::array<int, 10> arr = {};
虽然这仍然留下警告。
该警告包含在gcc 错误报告中:--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};
由于先前评论中所述的原因,这不应该发出警告。
后续评论说:
我关于零初始化的陈述不准确(谢谢),但一般观点仍然存在:在 C 中,您必须编写 '= {0}' 因为该语言不支持空括号初始化程序(您会收到 -pedantic 警告); 在 C++ 中,你可以写 '= {}' 或 'T foo = T();',但你不需要专门写 '= {0}'。
对于这种情况,最新版本的 gcc 不会产生此警告,请查看它与 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" };
将 ss.a 初始化为 1,将 ss.b 初始化为“asdf”,将 ss.c 初始化为 int() 形式的表达式的值,即 0。 —end example ]
因此这是有效的 C++,尽管如前所述 using{}
不是有效的 C99。有人可能会争辩说这只是一个警告,但这似乎是 C++{}
用于聚合初始化的惯用方式,如果我们-Werror
将警告转化为错误,则会出现问题。
首先,您可以将({})
初始化程序与std::array
对象一起使用,但在语义上代表使用来自临时值初始化std::array
对象的复制构造函数进行直接初始化,即它相当于
std::array<int, 10> arr(std::array<int, 10>{});
它实际上应该编译。
其次,当你能做到的时候,你真的不必走这({})
条路
std::array<int, 10> arr = {};
或者
std::array<int, 10> arr{};
两者中的第一个在语法上与 your 最相似int arr[10] = {};
,这让我想知道你为什么一开始没有尝试它。为什么您决定使用({})
而不是= {}
在构建语法std::array
版本时?= {}
有足够多的人在编译时指出这是一个“问题” -Werror
,我认为值得一提的是,如果你只是加倍,问题就会消失:
std::array<int, 10> arr{{}};
在 gcc 4.9.2 上不会对我产生任何警告。
补充一点为什么会解决它:我的理解是 std::array 实际上是一个以 C 数组作为其唯一成员的类。所以加倍大括号是有意义的:外大括号表示您正在初始化类,然后内大括号默认初始化类的唯一成员。
由于类中只有一个变量时不会产生歧义,因此只使用一对 {} 应该是合理的,但 gcc 在这里过于迂腐,并发出警告。