その理由は、クラスにユーザー定義のコンストラクターがない場合、それはPODになる可能性があり、PODクラスはデフォルトで初期化されないためです。では、初期化されていないPODのconstオブジェクトを宣言する場合、それをどのように使用しますか?したがって、オブジェクトが実際に役立つように、標準はこのルールを適用すると思います。
struct POD
{
int i;
};
POD p1; //uninitialized - but don't worry we can assign some value later on!
p1.i = 10; //assign some value later on!
POD p2 = POD(); //initialized
const POD p3 = POD(); //initialized
const POD p4; //uninitialized - error - as we cannot change it later on!
しかし、クラスを非PODにした場合:
struct nonPOD_A
{
nonPOD_A() {} //this makes non-POD
};
nonPOD_A a1; //initialized
const nonPOD_A a2; //initialized
PODと非PODの違いに注意してください。
ユーザー定義コンストラクタは、クラスを非PODにする1つの方法です。これを行うにはいくつかの方法があります。
struct nonPOD_B
{
virtual void f() {} //virtual function make it non-POD
};
nonPOD_B b1; //initialized
const nonPOD_B b2; //initialized
nonPOD_Bはユーザー定義コンストラクタを定義していないことに注意してください。コンパイルします。それはコンパイルされます:
そして、仮想関数をコメントすると、期待どおりにエラーが発生します。
ええと、あなたはその箇所を誤解していると思います。それは最初にこれを言います(§8.5/ 9):
オブジェクトに初期化子が指定されておらず、オブジェクトが(おそらくcvで修飾された)非PODクラス型(またはその配列)である場合、オブジェクトはデフォルトで初期化されます。[...]
非PODクラス、おそらくcv修飾型について話します。つまり、初期化子が指定されていない場合、非PODオブジェクトはデフォルトで初期化されます。そして、デフォルトで初期化されるものは何ですか?非PODの場合、仕様には(§8.5/ 5)とありますが、
タイプTのオブジェクトをデフォルトで初期化するとは、次のことを意味します
。— Tが非PODクラスタイプ(9節)の場合、Tのデフォルトコンストラクターが呼び出されます(Tにアクセス可能なデフォルトコンストラクターがない場合、初期化は正しくありません)。
Tのデフォルトコンストラクターについて話しているだけで、ユーザー定義またはコンパイラーが生成したものは関係ありません。
これまでに問題がなければ、次に仕様が言うことを理解してください((8.5 / 9)、
[...]; オブジェクトがconst修飾型の場合、基本となるクラス型にはユーザー宣言のデフォルトコンストラクターが必要です。
このテキストは暗示ので、プログラムが病気に形成される場合、オブジェクトがあるのconst修飾 PODのタイプ、および(PODが初期化デフォルトではありませんされているため)初期化子が指定されていません。
POD p1; //uninitialized - can be useful - hence allowed
const POD p2; //uninitialized - never useful - hence not allowed - error
ちなみに、これは非PODであり、デフォルトで初期化できるため、正常にコンパイルされます。
a
場合でもgcc-4.3.4はそれを受け入れます(ideone.com/uHvFSを参照)