値とデフォルトとゼロの初期化について非常に混乱しています。特に、異なる標準C++ およびC++ 11(およびC++ 14)を採用した場合。
私は引用して本当に良い答えを拡張しようとしています Value-/Default-/Zero- Init C++ 98 and C++ 誰かが必要なギャップを埋めて何がいつ起こるかについての良い概要を手伝うことができれば多くのユーザーを助けるので、より一般的にするためにここに?
一例での完全な洞察:
New演算子によって返されるメモリが初期化されることもあれば、更新する型が POD(plain old data) であるかどうか、またはそれがクラスであるかどうかに依存しないこともあります。 PODメンバーを含み、コンパイラー生成のデフォルトコンストラクターを使用しています。
仮定:
_struct A { int m; };
struct B { ~B(); int m; };
struct C { C() : m(){}; ~C(); int m; };
struct D { D(){}; int m; };
struct E { E() = default; int m;} /** only possible in c++11/14 */
struct F {F(); int m;} F::F() = default; /** only possible in c++11/14 */
_
C++ 98コンパイラでは、次のようになります:
new A
_-不定値(A
はPOD)new A()
-ゼロ初期化new B
_-デフォルトの構成(_B::m
_は初期化されていない、B
は非POD)new B()
-デフォルトの構成(_B::m
_は初期化されていません)new C
_-デフォルトの構成(_C::m
_はゼロで初期化され、C
は非PODです)new C()
-デフォルトの構成(_C::m
_はゼロで初期化されます)new D
_-デフォルトの構成(_D::m
_は初期化されていない、D
は非POD)new D()
-デフォルトの構成?(_D::m
_は初期化されていません)C++ 03準拠のコンパイラでは、次のように動作するはずです:
new A
_-不定値(A
はPOD)new A()
-value-initialize A
。これはPODであるためゼロで初期化されます。new B
_-デフォルトの初期化(_B::m
_は初期化せず、B
はPOD以外)new B()
-値の初期化B
は、デフォルトのctorがユーザー定義ではなくコンパイラ生成されるため、すべてのフィールドをゼロで初期化します。new C
_-デフォルトのctorを呼び出すC
をデフォルトで初期化します。 (_C::m
_はゼロで初期化され、C
は非PODです)new C()
-デフォルトのctorを呼び出すC
の値を初期化します。 (_C::m
_はゼロで初期化されます)new D
_-デフォルトの構成(_D::m
_は初期化されていない、D
は非POD)new D()
-value-initializes D?、これはデフォルトのctorを呼び出します(_D::m
_は初期化されていません)斜体の値と?不確実性は、これを修正するのを手伝ってください:-)
C++ 11準拠コンパイラでは、次のように動作するはずです:
??? (私がここから始めたら、とにかくうまくいかないので助けてください)
C++ 14準拠のコンパイラでは、次のように動作するはずです:??? (私がここから始めると、とにかく間違ってしまいます)(回答に基づいたドラフト)
new A
_-A
、コンパイラーgenをデフォルトで初期化します。 ctor、(leavs _A::m
_ uninitialized)(A
はPODです)new A()
-A
の値を初期化します。これは、2以来のゼロ初期化です。[dcl.init]/8
_new B
_-B
、コンパイラーgenをデフォルトで初期化します。 ctor、(leavs _B::m
_ uninitialized)(B
は非PODです)
new B()
-値の初期化B
は、デフォルトのctorがユーザー定義ではなくコンパイラ生成されるため、すべてのフィールドをゼロで初期化します。new C
_-デフォルトのctorを呼び出すC
をデフォルトで初期化します。 (_C::m
_はゼロで初期化され、C
は非PODです)new C()
-デフォルトのctorを呼び出すC
の値を初期化します。 (_C::m
_はゼロで初期化されます)new D
_-D
をデフォルトで初期化します(_D::m
_は初期化されず、D
は非PODです)new D()
-値の初期化D
は、デフォルトのctorを呼び出します(_D::m
_は初期化されていません)new E
_-compを呼び出すE
をデフォルトで初期化します。 gen。俳優。 (_E::m
_は初期化されておらず、Eは非PODです)new E()
-値の初期化E
。これは、[dcl.init]/8の2ポイント以降のE
をゼロで初期化します。new F
_-compを呼び出すF
をデフォルトで初期化します。 gen。俳優。 (_F::m
_は初期化されていない、F
は非POD)new F()
-value-initializes F
、これはdefault-initializesF
から1を指しています- [dcl.init]/8(F
ctor関数は、ユーザーが宣言し、最初の宣言で明示的にデフォルト設定または削除されていない場合、ユーザーが提供します。 Link )C++ 14は、[expr.new]/17のnew
(C++ 11の[expr.new]/15で作成されたオブジェクトの初期化を指定します。メモはメモではなく、規範的なテキストでした。その後):
タイプ
T
のオブジェクトを作成するnew-expressionは、そのオブジェクトを次のように初期化します。
- new-initializerが省略されている場合、オブジェクトはdefault-initialized(8.5)です。 [注:初期化が実行されない場合、オブジェクトの値は不確定です。 —終了ノート]
- それ以外の場合、new-initializerは、direct-initializationの8.5の初期化ルールに従って解釈されます。
デフォルトの初期化は[dcl.init]/7で定義されています(C++ 11の場合は/ 6、文言自体にも同じ効果があります):
タイプ
T
のオブジェクトをdefault-initializeするには、次のことを意味します。
T
が(おそらくcvで修飾された)クラス型(9項)の場合、T
のデフォルトコンストラクター(12.1)が呼び出されます(T
にはデフォルトのコンストラクタがないか、オーバーロード解決(13.3)があり、曖昧さや、初期化のコンテキストから削除された、またはアクセスできない関数になります。T
が配列型の場合、各要素はdefault-initialized;- それ以外の場合、初期化は実行されません。
かくして
new A
_は、A
sのデフォルトコンストラクターのみを呼び出し、m
を初期化しません。不定値。 _new B
_でも同じである必要があります。new A()
は[dcl.init]/11に従って解釈されます(C++ 11では/ 10):
イニシャライザが空の括弧のセット、つまり_
()
_であるオブジェクトは、値で初期化されます。
次に、[dcl.init]/8(C++ 11†の/ 7)を検討します。
タイプ
T
のオブジェクトをvalue-initializeするには、次のことを意味します。
T
が(おそらくcvで修飾された)クラス型(9項)であり、デフォルトコンストラクター(12.1)がないか、ユーザーが提供または削除するデフォルトコンストラクターの場合、オブジェクトはデフォルトで初期化されます。- _
T
がユーザー提供または削除されたデフォルトコンストラクターのない(おそらくcv修飾)クラスタイプである場合、オブジェクトはゼロで初期化され、デフォルトの初期化のセマンティック制約がチェックされ、 Tに重要なデフォルトコンストラクターがある場合、オブジェクトはデフォルトで初期化されます;T
が配列型の場合、各要素は値で初期化されます。- それ以外の場合、オブジェクトはゼロで初期化されます。
したがって、new A()
はm
をゼロで初期化します。そして、これはA
とB
で同等でなければなりません。
_new C
_およびnew C()
は、最後の引用符からの最初の箇条書きが適用されるため、オブジェクトを再びデフォルトで初期化します(Cにはユーザー提供のデフォルトコンストラクターがあります!)。しかし、明らかに、どちらの場合もm
がコンストラクターで初期化されます。
†さて、この段落にはC++ 11でわずかに異なる表現がありますが、結果は変わりません:
タイプ
T
のオブジェクトをvalue-initializeするには、次のことを意味します。
T
が(ユーザー定義のコンストラクター(12.1)を持つ(おそらくcvで修飾された)クラス型(9節)である場合、T
のデフォルトコンストラクターが呼び出されます(初期化は不正です) -Tにアクセス可能なデフォルトコンストラクターがない場合)T
が(ユーザー定義のコンストラクタを持たない(おそらくcvで修飾された)非共用クラス型である場合、オブジェクトはゼロで初期化され、T
の暗黙的に宣言されたデフォルトコンストラクタがnon -自明、そのコンストラクタが呼び出されます。T
が配列型の場合、各要素は値で初期化されます。- それ以外の場合、オブジェクトはゼロで初期化されます。