根据GCC 4.6.3(Ubuntu / Linaro 4.6.3-1ubuntu5)我在以下代码中的数组初始化中缺少大括号:
#include <iostream>
#include <boost/array.hpp>
#include <array>
int main(){
int plain[] = {1,2,3,4,5};
std::array <int, 5> std_arr = {1,2,3,4,5}; // warning, see below
boost::array<int, 5> boost_arr = {1,2,3,4,5}; // warning, see below
std::cout << plain[0] << std_arr[1] << boost_arr[2] << std::endl;
}
> g++ test.cc -Wall -Wextra -pedantic --std=c++0x test.cc: in function »int main()«: test.cc:7:47: warning: curly braces missing around initialization for »std::array::value_type [5] {aka int [5]}« [-Wmissing-braces] test.cc:8:47: warning: curly braces missing around initialization for »int [5]« [-Wmissing-braces]
显然(GCC missing braces around initializer)这是GCC中的一个错误,即使在稍微不同的背景下也是如此。答案不同于“提交错误报告”到“只是禁用警告”。
但是,在std::array
或boost::array
的情况下,这个警告是多余的,还是我遗漏了一些重要内容?
(我可能会添加额外的括号,而不是禁用警告,但我对这些含义感到好奇)
答案 0 :(得分:5)
我认为已经回答here。
std :: array很有趣。它的定义基本上是这样的:
template struct std :: array {T a [size]; };
它是一个包含数组的结构。它没有构造函数 这需要一个初始化列表。但是std :: array是一个聚合的 C ++ 11的规则,因此可以通过聚合创建 初始化。要聚合初始化struct中的数组, 你需要第二组花括号:
std :: array strings = {{“a”,“b”}};
请注意,该标准确实表明额外的括号可以 在这种情况下被忽略了。所以它可能是一个GCC错误。
我认为它可能与this defect有关,answer regarding it已在几个问题中联系起来。
这是http://gcc.gnu.org/ml/gcc-patches/2012-03/msg00215.html:
但是,这些额外的括号可能只能在“宣言中”中删除 形式T x = {a};“(C ++11§8.5.1/ 11),即旧式 =使用。允许括号省略的此规则不适用于直接列表初始化。这里的一个脚注写着:“大括号不能被省略 在列表初始化的其他用途中。“
有关此限制的缺陷报告:CWG缺陷 #1270。如果采用提议的解决方案,则允许使用大括号来进行其他形式的列表初始化,...
我注意到错误没有出现在gcc 4.8.1中,但它确实出现在一个非常旧的版本(4.4.7)上,我认为这是补丁(因为提出了缺陷解决方案的日期为2012年2月,此链接的日期为2012年3月):
{{3}}
答案 1 :(得分:3)
这是一个恼人的“安全”警告,它是在早期版本的GCC中为C和C ++聚合初始化器引入的。如果我没记错的话,它早于C ++ 11并且与C ++ 11并不真正相关(同样,它会影响C,因为它会影响C ++)。基本上,在为每个嵌套聚合开始初始化程序时,它需要额外级别的嵌套{}
。该语言不需要这个,这就是为什么它只是一个警告。
有问题的警告在许多情况下可能有用,但实施工作却很少考虑。该警告的一个完全荒谬的后果是它用C语言“杀死”= { 0 }
初始化者习惯用语。 (在C中,任何东西都可以用= { 0 }
初始化,但由于这个恼人的警告,人们不得不选择性地使用诸如= {{0}}
,= {{{0}}}
之类的东西。
在C ++中std::array
类是一个聚合,其中= { ... }
初始值设定项由旧的内置聚合初始化处理,而不是由专用的构造函数处理。 (在C ++ 11中,聚合初始化的规则是根据初始化列表重写的,但是通过大括号的可能性故意保留了一般的C风格行为。 )因此std::array
初始化也会受到该警告的影响。 std::array
是包含实际数组的聚合,实际数组也是聚合。因此,为了获取初始化程序中的数组元素,GCC鼓励您打开两个级别的{}
。
所以,对于std::array
,您刚刚找到了另一个例子,说明该警告何时弊大于利。
答案 2 :(得分:2)
不,对于一个简单的类来说,合理的编译器真的没办法解决这个问题。