忽略gcc / clang的“-Wmissing-Braces”警告是明智的吗?
考虑下面的程序:
#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]
…和铿锵3.1
main.cpp:5:28: warning: suggest braces around initialization of subobject [-Wmissing-braces] std::array<int, 1> x = { 0 };
就标准而言,至less在这个例子中,双花括号或单花括号应该没有区别。
有两种方法来处理警告:
- 把它关掉
- 修复代码,所以编译器很开心
你有什么build议? 恕我直言,双curlexpression看起来有些丑陋。 另一方面,这个警告可能会在更复杂的例子中发现真正的问题。 你知道一个警告会帮助你的例子吗?
-Wmissing-braces
你所描述的那样,在GCC的-Wall
(对于C ++模式)中,不再使用-Wmissing-braces
,从4.8开始。 对于当前版本的GCC,无论是禁用还是忽略警告,你所拥有的代码都是按照它的方式写的。
该警告可能是为了涵盖如下代码
struct A { int a; int b; }; struct B { A a; int b; }; B b = { 1, 2 // initialises bab, not bb };
但是,恕我直言,这是已经足够-Wmissing-field-initializers
处理,通过-Wmissing-field-initializers
,它不会警告你的原始代码。
我在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个元素的逗号分隔列表,其types可转换为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时,我们看到'initializer-list'可以select性地包含'initializer-clause',它本身可以是一个'braced-init-list'。 所以无论哪种方式应该是正确的 虽然基于规范我个人认为单个大括号不应该输出一个std ::数组初始化列表的编译器警告,双大括号是矫枉过正。
当用-Wno-missing-braces
忽略Clang警告时,我build议启用-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", ai, a.arr[0], a.arr[1], aj); } 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)
作为比较,这是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}; ^
综上所述:
- 对于Clang,我会build议
-Wno-missing-braces -Wmissing-field-initializers
在不丢失其他有用警告的情况下使警告-Wno-missing-braces -Wmissing-field-initializers
- GCC不会抱怨原始的
std::array<int, 1> x = { 0 };
例如,所以没有必要禁用任何警告。 但是,我build议启用-Wmissing-field-initializers
(或使用-Wextra
),因为它不是由-Wall
启用的。