3

重複の可能性:
C ++で次のフレーズはどういう意味ですか:ゼロ、デフォルト、および値の初期化?

今日、私はC++での3種類の初期化について知るようになりました。

  • ゼロ初期化
  • デフォルトの初期化
  • 値の初期化

私はそれについてグーグルで検索しましたが、満足のいく結果は見つかりませんでした。私が得るのはいくつかの基準だけです。これまで私が理解していたのは、これです。値の初期化の場合、データメンバーは場合によってはゼロに等しい値を取得できます。

それら(標準)を例を挙げて詳しく説明してください。また、標準のテキストだけを提供しないでください。

ありがとう

4

2 に答える 2

6

初期化のタイプは、言語の文法を参照します。次に2つの例を示します。

T * p1 = new T;
T * p2 = new T();

オブジェクト*p1はデフォルトで初期化され、オブジェクト*p2は値で初期化されます。

初期化の効果はタイプによって異なりますT:1)Tが基本である場合、デフォルト初期化は何もしません(つまり、オブジェクトは初期化されないままになります)が、値の初期化はその場合ゼロ初期化に等しく、オブジェクトがゼロに設定されることを意味します。

2)Tが集合体(つまり、コンストラクタ、デストラクタ、または代入演算子のないクラス)の場合、各要素は再帰的にデフォルトまたは値で初期化されます。

3)Tがクラスタイプであり、ユーザー定義のコンストラクターがある場合、デフォルトと値の両方の初期化により、デフォルトのコンストラクターが呼び出されます。

コンストラクターを持つクラスのメンバーオブジェクトは、デフォルトまたは値で初期化できることに注意してください。

struct Foo {
    int x;
    int y;
    Foo() : x() { }
};

さて、あなたが言うとき、Foo a;それaはデフォルトで初期化されているので、デフォルトのコンストラクターが呼び出されます。これによりa.x、値、つまりゼロで初期化されますが、a.yデフォルトのまま、つまり初期化されません。

(自動オブジェクトの値を初期化することは実際には不可能であることに注意してください。ただし、C ++ 11では、中括弧の初期化を使用して、のように値の初期化を行うことができます。(これは、この例Foo a{};とまったく同じように動作します。 Foo a;3番目の段落。))

于 2012-02-18T16:18:38.460 に答える
3

これは8.5イニシャライザー[dcl.init]で処理されます。


ゼロ初期化

5 /オブジェクトまたはタイプの参照をゼロで初期化するには、次のことをT意味します。

Tがスカラー型(3.9)の場合、オブジェクトは値0(ゼロ)に設定され、積分定数式と見なされ、に変換されTます。4.10で指定されているように、値が0の整数定数式をポインター型に変換すると、ポインター値がnullになります。

Tが(おそらくcv修飾された)非ユニオンクラスタイプの場合、各非静的データメンバーと各基本クラスサブオブジェクトはゼロで初期化され、パディングはゼロビットに初期化されます。

Tが(おそらくcv修飾された)共用体型の場合、オブジェクトの最初の非静的な名前付きデータメンバーはゼロ初期化され、パディングはゼロビットに初期化されます。

Tが配列型の場合、各要素はゼロで初期化されます。

Tが参照型の場合、初期化は実行されません。

memset(&obj, 0, sizeof(objt));基本的に、これは、nullポインタのメモリ表現が0値ではない可能性があることを考慮していることを除いて、と同等です(言語では0で表されている場合でも)。

// foo.cpp
static char const* p;     // p is zero-initialized
                          // during static initialization

static void init() {
  if (!p) { p = new char[500]; }  // fine as p has been 0-initialized
}

注:個人的には、意図を明確にするために、= nullptr初期化に使用することを好みます...p


デフォルトの初期化

6 /デフォルトにするには-タイプのオブジェクトを初期化するということは、次のことをT意味します。

Tが(おそらくcv修飾された)クラスタイプ(第9節)の場合、のデフォルトコンストラクターTが呼び出されます(Tアクセス可能なデフォルトコンストラクターがない場合、初期化は不正な形式になります)。

Tが配列型の場合、各要素はデフォルトで初期化されます。

—それ以外の場合、初期化は実行されません。

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

または、基本的に、少なくともクラスの配列を考慮した、デフォルトのコンストラクターの呼び出し。最後のポイントは、ビルトイン(などint)に関する警告です。それらはそのまま残されます(ゴミが入っています)。

デフォルトの初期化は、変数を定義したときに呼び出されるものですが、明示的に初期化しないでください。これは、初期化子リストにリストされていないクラスの属性にも起こります。したがって、ビルトインに関する警告は、プログラマーにとって非常に重要です。

int function() {
  int a;         // <-- a is default-initialized (which means nothing happens...)
  return a;      // <-- uses a, so technically undefined behavior
}

struct A { int a; A() {} }; // During the call to A::A(),
                            // A::a is default-initialized (nothing happens...)

明示的な初期化がないことはCからの残りです。通常は最適化の理由でそうですが、値を使用しようとすると未定義動作になります。


値の初期化

7 /タイプのオブジェクトを値初期化するには、次のことをT意味します。

Tが(おそらくcv修飾された)クラスタイプ(第9節)で、ユーザー提供のコンストラクター(12.1)がある場合、のデフォルトコンストラクターTが呼び出されます(Tアクセス可能なデフォルトコンストラクターがない場合、初期化は不正な形式になります)。

Tが(おそらくcv修飾された)非ユニオンクラスタイプであり、ユーザー提供のコンストラクターがない場合、オブジェクトはゼロで初期化され、T暗黙的に宣言されたデフォルトコンストラクターが自明でない場合、そのコンストラクターが呼び出されます。

Tが配列型の場合、各要素は値で初期化されます。

—それ以外の場合、オブジェクトはゼロで初期化されます。

値が初期化されたオブジェクトは構築されたと見なされるため、オブジェクトのコンストラクターが呼び出されない場合でも、「構築された」オブジェクト、「コンストラクターが完了した」オブジェクトなどに適用されるこの国際規格の規定の対象となります。初期化。

これは、上記の両方を組み合わせたものであり、次の構文を意味します。

template <typename T> T value() { return T(); }
                                         ^~~

クラス型か組み込み型Tかを適切に初期化したインスタンスを提供します。Tテンプレート化されたコードがそのような統一された構文を持つことができることが重要です。

T{}C ++ 11では、同じ効果を達成するために使用することも可能であることに注意してください(これは関数からの明確化に役立ちます)。

于 2012-02-18T16:39:53.620 に答える