16

これは、現在の MSVC コンパイラで完全に正常にコンパイルされます。

struct Foo
{
} const foo;

ただし、現在の g++ コンパイラではコンパイルに失敗します。

error: uninitialized const 'foo' [-fpermissive]
note: 'const struct Foo' has no user-provided default constructor

自分でデフォルトのコンストラクターを提供すると、機能します。

struct Foo
{
    Foo() {}
} const foo;

これは、MSVC が寛容すぎる別のケースですか、それともここでは g++ が厳しすぎるのでしょうか?

4

4 に答える 4

15

C++03 標準:

8.5 [dcl.init] パラグラフ 9

オブジェクトに初期化子が指定されておらず、オブジェクトが (おそらく cv 修飾された) 非 POD クラス型 (またはその配列) である場合、オブジェクトはデフォルトで初期化されます。オブジェクトが const 修飾された型の場合、基になるクラス型には、ユーザーが宣言した既定のコンストラクターが必要です。

上記から、gcc のエラーは完全に有効であるように思われます。

于 2011-11-11T10:38:14.790 に答える
5

[2003: 8.5/9]: オブジェクトに初期化子が指定されておらず、オブジェクトが (おそらく cv 修飾された) 非 POD クラス型(またはその配列) である場合、オブジェクトはデフォルトで初期化されます。オブジェクトが const 修飾された型の場合、基になるクラス型には、ユーザーが宣言した既定のコンストラクターが必要です。それ以外の場合、非静的オブジェクトに対して初期化子が指定されていない場合、オブジェクトとそのサブオブジェクト (存在する場合) の初期値は不確定です。オブジェクトまたはそのサブオブジェクトのいずれかが const 修飾された型である場合、プログラムは不正な形式です。

と:

[n3290: 8.5/11]: オブジェクトに初期化子が指定されていない場合、オブジェクトはデフォルトで初期化されます。初期化が実行されない場合、自動または動的ストレージ期間を持つオブジェクトの値は不定になります。[注:静的またはスレッド ストレージ期間を持つオブジェクトは、ゼロで初期化されます。3.6.2._ を参照してください —終了注_ ]

[n3290: 8.5/6]:タイプのオブジェクトをデフォルトで初期化Tするとは、次のことを意味します。

  • T(おそらく cv 修飾された) クラス型 (第 9 節) の場合、T の既定のコンストラクターが呼び出されます (アクセス可能な既定のコンストラクターがない場合、初期化の形式は正しくありTません)。
  • が配列型の場合T、各要素はデフォルトで初期化されます。
  • それ以外の場合、初期化は実行されません。

プログラムが const 修飾された型のオブジェクトのデフォルトの初期化を呼び出す場合、ユーザー提供のデフォルト コンストラクターを持つクラス型Tでなければなりません。T

したがって、MSVC は、両方の標準の義務よりも寛容です。

于 2011-11-11T10:41:22.683 に答える
2

標準の正確な文言はわかりませんが、g++ のエラーは、何も言わないというオプションよりもかなり賢明なようです。このことを考慮:

struct X {
   int value;
};
const X constant; // constant.value is undefined

ユーザー提供のデフォルト コンストラクターの場合は (何もしない場合でも)、コンパイラーはそのコンストラクターを呼び出し、オブジェクトは初期化されます (コンストラクターに実装した初期化の定義によって)。

于 2011-11-11T10:35:21.073 に答える