忽视gcc / clang的“-Wmissing-braces”警告是明智的吗?

时间:2012-12-16 20:31:32

标签: c++ c++11 compiler-warnings

考虑以下计划:

#include <array>

int main()
{
  std::array<int, 1> x = { 0 }; // warning!
  x = { { 0 } }; // no warning
  return 0;
}

第一次初始化导致gcc 4.7.2 ...

上的警告
main.cpp:5:22: warning: unused variable ‘x’ [-Wunused-variable]

...和clang 3.1

main.cpp:5:28: warning: suggest braces around initialization of subobject [-Wmissing-braces]
  std::array<int, 1> x = { 0 };

就标准而言,双花键或单花括号之间应该没有区别,至少在这个例子中是这样。

有两种方法可以处理警告:

  1. 关掉它
  2. 修复代码,编译器很高兴
  3. 你有什么建议?恕我直言,双卷曲表达看起来有些难看。另一方面,警告可能会在更复杂的示例中检测到实际问题。你知道这个警告对你有帮助的例子吗?

4 个答案:

答案 0 :(得分:46)

-Wmissing-braces will no longer be enabled in GCC's -Wall (for C++ mode), as of 4.8, for precisely the reason you describe.对于GCC的当前版本,无论是禁用还是忽略警告,您所拥有的代码都应该按照应有的方式编写。

警告可能是为了涵盖诸如

之类的代码
struct A { int a; int b; };
struct B { A a; int b; };
B b = {
  1,
  2 // initialises b.a.b, not b.b
};

然而,恕我直言,-Wmissing-field-initializers已经处理得足够好了,并没有警告你的原始代码。

答案 1 :(得分:7)

我在Xcode 6.1.1(截至2015年3月9日的当前版本)中收到相同的警告。当我在每个子对象周围添加额外的大括号时,我收到错误。当我在整个初始化列表周围添加一组额外的大括号时,警告就会消失。根据标准规范14882:2011 23.3.2.1 [array.overview]第2小节明确说明

array<T, N> a = { initializer-list };
  

其中initializer-list是最多包含N个元素的逗号分隔列表   其类型可转换为T

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

当我们查看14882:2011 8.5 [dcl.init]第1小节时,我们会看到&#39;初始化列表&#39;可以选择包含一个&quot; initializer-clause&#39 ;,它本身可以是一个&braff-init-list&#39;。所以两种方式都应该是正确的。虽然根据规范,我个人认为单个大括号不应该输出std :: array initializer-list的编译器警告,而双括号是过度的。

答案 2 :(得分:4)

Clang 6.0禁止删除大括号的警告。 svn日志说:

  

使用单个字段聚合初始化结构时抑制-Wmissing-braces警告,该字段本身就是一个聚合。在C ++中,std :: array类型的这种初始化保证按标准工作,完全是惯用的,而且#34;建议&#34;替代   Clang在技术上无效。

所以如果需要支持,我会省略大括号并为6.0之前的Clang禁用-Wmissing-braces

答案 3 :(得分:3)

当忽略-Wno-missing-braces的Clang警告时,我建议您启用-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)
$ 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};
                 ^

为了比较,这就是GCC的作用:

-Wno-missing-braces -Wmissing-field-initializers

总结:

  • 对于Clang,我建议std::array<int, 1> x = { 0 };在不丢失其他有用警告的情况下使警告静音
  • GCC不会在原始-Wmissing-field-initializers示例中投诉,因此无需禁用任何警告。不过,我建议启用-Wextra(或使用-Wall),因为{{1}}未启用此功能。