初始化时真的需要大括号吗
Are curly braces really required around initialization?
根据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++0xtest.cc:在函数中»int main()«:test.cc:7:47:警告:初始化»std::array::value_type[5]{aka int[5]}«[-Wmissing braces]时缺少大括号test.cc:8:47:警告:初始化»int[5]«[-Wmissing brackets]时缺少大括号
显然(GCC在初始值设定项周围缺少大括号)这是GCC中的一个错误,即使在稍微不同的上下文中也是如此。答案不同于"提交错误报告"answers"仅禁用警告"。
然而,在std::array
或boost::array
的上下文中,这个警告是多余的,还是我遗漏了一些重要的东西?
(我可能会添加额外的大括号,而不是禁用警告,但我很好奇其含义)
我想这里已经回答了这个问题。
std::array很有趣。它的定义基本上是这样的:
模板结构std::数组{T a〔size〕;};
它是一个包含数组的结构。它没有构造函数需要一个初始值设定项列表。但是std::array是C++11的规则,因此它可以通过聚合创建初始化。为了聚合初始化结构内部的数组,你需要第二套大括号:
std::array字符串={{"a","b"}};
请注意,该标准确实建议额外的支架可以在这种情况下被忽略。所以它很可能是一个GCC错误。
我相信这可能与这个缺陷有关,这个缺陷在几个问题上都有联系。
以下是关于它的答案:
然而,这些额外的大括号只能在形式T x={a};"(C++11§8.5.1/11),即当使用=。此允许省略大括号的规则不适用于直接列表初始化。这里的脚注写道:"括号不能省略在列表初始化的其他用途中。"
有一份关于该限制的缺陷报告:CWG缺陷#1270.如果所提出的决议获得通过,将允许对其他形式的列表初始化省略大括号。。。
我注意到这个错误没有出现在gcc 4.8.1中,但它出现在一个非常旧的版本上(4.4.7),我认为这就是补丁(因为缺陷提出的解决方案日期为2012年2月,而这个链接日期为2012月3月):
http://gcc.gnu.org/ml/gcc-patches/2012-03/msg00215.html
这是一个烦人的"安全"警告,它是在早期版本的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
,您刚刚发现了另一个警告弊大于利的例子。
不,对于一个如此简单的类,一个合理的编译器真的不可能把它搞砸。
- 是否可以初始化不可复制类型的成员变量(或基类)
- C++使用整数的压缩数组初始化对象
- C++初始化基类
- 多成员Constexpr结构初始化
- 复制列表初始化的隐式转换的等级是多少
- 内联映射初始化的动态atexit析构函数崩溃
- 如何在C++中初始化嵌套类中的2个memeber
- 如何声明特征矩阵,然后通过嵌套循环初始化它
- 没有用于初始化C++中的变量模板的匹配构造函数
- 在未初始化映射的情况下,将值插入到映射的映射中
- C++成员初始化
- 为什么在C++中首先初始化成员类
- 同时具有"聚合初始化"和"模板推导"
- 初始化具有非默认构造函数的std::数组项的更好方法
- 是否可以在编译时初始化数组,以便在运行时不会花费时间?
- 我可以使用条件运算符初始化C风格的字符串文字吗
- Visual Studio 2017 允许在构造函数中使用自身初始化引用成员.真的是合法的C++吗?
- 初始化时真的需要大括号吗
- 在按值传递的重成员的构造函数初始化列表中是否真的需要std::move ?
- 不管是否初始化,使用sizeof(p[0])真的无害吗?