54

次のプログラムを検討してください。

#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 };

標準に関する限り、少なくともこの例では、二重中括弧と単一中括弧の間に違いはないはずです。

警告に対処するには、次の 2 つの方法があります。

  1. オフにするだけ
  2. コードを修正して、コンパイラが満足するようにします

あなたは何を提案しますか?IMHO、二重巻き毛の表現はやや醜く見えます。一方、警告は、より複雑な例で実際の問題を検出する場合があります。警告が役に立った例を知っていますか?

4

4 に答える 4

52

-Wmissing-braces-Wallあなたが説明した正確な理由により、4.8以降、GCC(C++モード用)では有効になりません。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、元のコードについて警告することはありません。

于 2012-12-16T20:59:15.380 に答える
8

Xcode 6.1.1 (2015 年 3 月 9 日現在のバージョン) でも同じ警告が表示されます。各サブオブジェクトの周りに中かっこを追加すると、エラーが発生します。初期化リスト全体に中括弧のセットを追加すると、警告が消えます。標準仕様 14882:2011 23.3.2.1 [array.overview] サブセクション 2 によると、明示的に述べられています

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

ここで、initializer-list は、型が T に変換可能な最大 N 個の要素のカンマ区切りのリストです

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」にはオプションで「initializer-clause」を含めることができ、それ自体が「braced-init-list」になる場合があることがわかります。したがって、どちらの方法も正しいはずです。仕様に基づいていますが、個人的には、単一のブレースは std::array 初期化子リストのコンパイラ警告を出力すべきではないと思います。二重ブレースはやり過ぎです。

于 2015-03-09T07:05:39.157 に答える
3

で 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)

比較のために、これは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 の場合、-Wno-missing-braces -Wmissing-field-initializers他の有用な警告を失うことなく、警告を黙らせることをお勧めします
  • 元の例では GCC は文句を言わないstd::array<int, 1> x = { 0 };ので、警告を無効にする必要はありません。ただし、 では有効にならないため、有効にする-Wmissing-field-initializers(または使用する-Wextra)ことをお勧めし-Wallます。
于 2016-08-29T15:26:40.753 に答える