C++ 忽略 gcc/clang 的“-Wmissing-braces”警告是否明智?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/13905200/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Is it wise to ignore gcc/clang's "-Wmissing-braces" warning?
提问by Philipp Cla?en
Consider the following program:
考虑以下程序:
#include <array>
int main()
{
std::array<int, 1> x = { 0 }; // warning!
x = { { 0 } }; // no warning
return 0;
}
The first initialization leads to warnings on gcc 4.7.2...
第一次初始化导致 gcc 4.7.2 上的警告...
main.cpp:5:22: warning: unused variable ‘x' [-Wunused-variable]
... and clang 3.1
...和叮当 3.1
main.cpp:5:28: warning: suggest braces around initialization of subobject [-Wmissing-braces]
std::array<int, 1> x = { 0 };
As far as the standard goes, there should be no difference between double or single curly braces, at least in this example.
就标准而言,双花括号或单花括号之间应该没有区别,至少在这个例子中是这样。
There are two ways to deal with the warning:
有两种方法可以处理警告:
- Just turn it off
- Fix the code, so the compiler is happy
- 把它关掉
- 修复代码,让编译器开心
What do you propose? IMHO, the double curly expression looks somewhat ugly. On the other hand, the warning might detect real problems in more complicated examples. Do you know an example where the warning would have helped you?
你有什么建议?恕我直言,双卷曲的表情看起来有点难看。另一方面,警告可能会在更复杂的示例中检测到实际问题。您知道警告会对您有帮助的示例吗?
采纳答案by Philipp Cla?en
-Wmissing-braces
will no longer be enabled in GCC's -Wall
(for C++ mode), as of 4.8, for precisely the reason you describe.For current versions of GCC, either disable or ignore the warning, the code you have is written the way it should be.
-Wmissing-braces
-Wall
从 4.8 开始,将不再在 GCC (对于 C++ 模式)中启用,这正是您描述的原因。对于当前版本的 GCC,无论是禁用还是忽略警告,您所拥有的代码都是按照应有的方式编写的。
The warning is probably meant to cover code such as
该警告可能旨在涵盖诸如
struct A { int a; int b; };
struct B { A a; int b; };
B b = {
1,
2 // initialises b.a.b, not b.b
};
However, IMHO, that is already handled well enough by -Wmissing-field-initializers
, which does not warn about your original code.
但是,恕我直言, 已经处理得足够好-Wmissing-field-initializers
,它不会警告您的原始代码。
回答by Robert Blair Aldridge
I get the same warning in Xcode 6.1.1 (the current version as of March 9, 2015). When I add the extra braces around each subobject I get an error. When I add an extra set of braces around the entire initialization list then the warning goes away. According to the standard specification 14882:2011 23.3.2.1 [array.overview] subsection 2 explicitly states
我在 Xcode 6.1.1(截至 2015 年 3 月 9 日的当前版本)中收到相同的警告。当我在每个子对象周围添加额外的大括号时,我得到一个错误。当我在整个初始化列表周围添加一组额外的大括号时,警告就会消失。根据标准规范 14882:2011 23.3.2.1 [array.overview] subsection 2 明确指出
array<T, N> a = { initializer-list };
where initializer-list is a comma-separated list of up to N elements whose types are convertible to T
其中 initializer-list 是最多 N 个元素的逗号分隔列表,其类型可转换为 T
result of code in Xcode 6.1.1 (below)
Xcode 6.1.1 中的代码结果(下)
array<int, 2> key1 = {1, 2}; // warning: suggest braces around initialization of subobject
array<int, 2> key2 = { {1}, {2} }; // error: no viable overload =
array<int, 2> key3 = array<int, 2> { {1}, {2} }; // error: excess elements in struct initializer
array<int, 2> key4 = { {1, 2} }; // no warning and no error
When we look at 14882:2011 8.5 [dcl.init] subsection 1 we see that an 'initializer-list' can optionally contain an 'initializer-clause', which itself can be a 'braced-init-list'. So either way should be correct. Though based on the spec I personally think single braces shouldn't output a compiler warning for a std::array initializer-list, and double braces is overkill.
当我们查看 14882:2011 8.5 [dcl.init] 小节 1 时,我们看到“初始化列表”可以选择包含“初始化条款”,它本身可以是“支撑初始化列表”。所以无论哪种方式都应该是正确的。虽然基于规范,我个人认为单大括号不应该为 std::array 初始值设定项列表输出编译器警告,而双大括号是矫枉过正。
回答by proski
Clang 6.0 suppresses the warning about missing braces. The svn log says:
Clang 6.0 取消了有关缺少大括号的警告。svn 日志说:
Suppress -Wmissing-braces warning when aggregate-initializing a struct with a single field that is itself an aggregate. In C++, such initialization of std::array types is guaranteed to work by the standard, is completely idiomatic, and the "suggested" alternative from Clang was technically invalid.
当聚合初始化一个结构体时,抑制 -Wmissing-braces 警告,该结构体本身就是一个聚合体。在 C++ 中,std::array 类型的这种初始化由标准保证工作,完全是惯用的,而 Clang 的“建议”替代方案在技术上是无效的。
So I would omit the braces and disable -Wmissing-braces
for Clang prior to 6.0 if it needs to be supported.
因此-Wmissing-braces
,如果需要支持,我会在 6.0 之前省略大括号并禁用Clang。
回答by Philipp Cla?en
When ignoring the Clang warning with -Wno-missing-braces
, I would recommend to enable -Wmissing-field-initializers
(or use -Wextra
, which also includes it). Otherwise, you miss a useful warning like in this example:
使用 忽略 Clang 警告时-Wno-missing-braces
,我建议启用-Wmissing-field-initializers
(或使用-Wextra
,其中也包括它)。否则,您会错过一个有用的警告,如本例所示:
#include <cstdio>
struct A
{
int i;
int arr[2];
int j;
};
void print(const A& a)
{
printf("i=%d, arr={%d,%d}, j=%d\n", a.i, a.arr[0], a.arr[1], a.j);
}
int main() {
A a = {1, 2, 3}; // this is the critical line
print(a); // output: i=1, arr={2,3}, j=0
A b = {1, {2}, 3};
print(b); // output: i=1, arr={2,0}, j=3
A c = {1, {2,0}, 3};
print(c); // output: i=1, arr={2,0}, j=3
return 0;
}
$ clang++ -Wall example.cpp
example.cpp:16:13: warning: suggest braces around initialization of
subobject [-Wmissing-braces]
A a = {1, 2, 3};
^~~~
{ }
1 warning generated.
$ clang++ -Wall -Wno-missing-braces example.cpp
(no warnings)
$ clang++ -Wall -Wno-missing-braces -Wmissing-field-initializers example.cpp
example.cpp:16:17: warning: missing field 'j' initializer
[-Wmissing-field-initializers]
A a = {1, 2, 3};
^
1 warning generated.
$ clang++ --version
clang version 3.8.1 (tags/RELEASE_381/final)
For comparison, this is what GCC does:
为了比较,这就是 GCC 所做的:
$ g++ -Wall -Wextra example.cpp
(no warning)
$ g++ -Wall -Wmissing-field-initializers example.cpp
example.cpp: In function ‘int main()'
example.cpp:16:17: warning: missing initializer for member ‘A::j' [-Wmissing-field-initializers]
A a = {1, 2, 3};
^
In summary:
总之:
- For Clang, I would recommend
-Wno-missing-braces -Wmissing-field-initializers
to silence the warning without loosing other useful warnings - GCC does not complain in the original
std::array<int, 1> x = { 0 };
example, so there is no need to disable any warnings. However, I would recommend to enable-Wmissing-field-initializers
(or use-Wextra
), as it is not enabled by-Wall
.
- 对于 Clang,我建议
-Wno-missing-braces -Wmissing-field-initializers
在不丢失其他有用警告的情况下关闭警告 - GCC 在原始
std::array<int, 1> x = { 0 };
示例中没有抱怨,因此无需禁用任何警告。但是,我建议启用-Wmissing-field-initializers
(或使用-Wextra
),因为它不是由-Wall
.