ここでの初期化cMyConstDouble2をこれに変更すると:
const double cMyConstDouble2 = 2.5*3.14;
その後、プログラムは正しく動作するはずです。その理由は、
静的初期化時に初期化されます。これらの初期化には、
- 静的ストレージ期間を持つすべてのオブジェクトのゼロ初期化
- 定数式で初期化された POD の初期化
表示された変数のうち、cMyConstDouble静的初期化時に完全に初期化されるという両方の条件のみを満たします。ただし、cMyConstDouble2その初期化子が定数式の要件を満たさないため、そうではありません。特に、整数型を持たない変数 (ここでは浮動小数点型) が含まれます。ただし、算術定数式では浮動小数点リテラル を使用できます。2.5*3.14これが算術定数式である理由です。そのため、イニシャライザをそのように変更するには、静的に初期化する必要があります。
cMyConstDouble2非定数式のままだとどうなりますか? 答えは、わかりません。標準では、その変数を静的に初期化することを許可していますが、そうする必要はありません。あなたの場合、それは動的に初期化されました-したがって、静的初期化時間の直後の値はまだゼロでした。それがいかに複雑かを理解するために、以下に例を示します。
inline double fd() { return 1.0; }
extern double d1;
double d2 = d1; // unspecified:
// may be statically initialized to 0.0 or
// dynamically initialized to 1.0
double d1 = fd(); // may be initialized statically to 1.0
動的初期化が他の静的ストレージ変数を変更しない場合 (コードで満たされている場合)、および静的初期化が、静的に初期化する必要のないすべてのオブジェクトが動的に初期化されるときに動的初期化によって生成される値と同じ値を生成する場合 (コードでも満足されます) - 変数を静的に初期化することが許可されます。d2これらの 2 つの条件は、変数との両方について、上記のコードでも満たされていますd1。
の分析d2
= d1他の静的ストレージ変数は変更しません
d2との両方d1が動的に初期化される場合、d2は に初期化されます。これは、 が の前に定義され0.0ているためです。また、 の動的初期化は、静的初期化の直後の状態での値を取得します (ゼロ初期化のみが行われた場所)。d2d1d2d1d1
の分析d1
= fd()他の静的ストレージ変数は変更しません
d2との両方d1が動的に初期化されると、= fd()は に初期化d1され1.0ます。
したがって、optional-static-initialization の両方の条件が満たされるため、コンパイラはd1に静的に初期化できます。1.0
ただし、の値d2がいつd1 で、 d2静的に初期化されるかはわかりません。つまり、静的初期化の順序が定義されていないため、 がまたはd2を取得する必要があるかどうかです。0.01.0
(1)静的記憶域期間を持つオブジェクトの初期化順序を考慮する場合、定数式には (整数定数式だけでなく) 算術定数式も含まれます。