1. ホーム
  2. c++

[解決済み] C++ ゼロ初期化 - なぜこのプログラムでは `b` は初期化されないのに `a` は初期化されるのですか?

2022-06-02 21:09:14

質問

の回答として認められている(そして唯一の)答えによると このStack Overflowの質問 ,

<ブロッククオート

でコンストラクタを定義する。

MyTest() = default;

は、代わりにオブジェクトをゼロ初期化します。

ではなぜ以下のようになるのか。

#include <iostream>

struct foo {
    foo() = default;
    int a;
};

struct bar {
    bar();
    int b;
};

bar::bar() = default;

int main() {
    foo a{};
    bar b{};
    std::cout << a.a << ' ' << b.b;
}

はこのような出力をします。

0 32766

定義されているコンストラクタはどちらもデフォルト?ですよね?そしてPOD型はデフォルトの初期化はゼロ初期化です。

そして、受け入れられた答えによると この質問 ,

  1. POD メンバがコンストラクタでも C++11 のクラス内初期化でも初期化されない場合、デフォルトで初期化されます。 クラス内初期化でも初期化されない場合、デフォルトで初期化されます。

  2. スタックやヒープに関係なく、答えは同じです。

  3. C++98 (およびそれ以降) では、new int() はゼロ初期化を実行するように指定されていました。 ゼロ初期化を行うように指定されていました。

私の(とはいえ)ラップをしようとしたにもかかわらず 小さな を理解しようとしているにもかかわらず デフォルトコンストラクタ デフォルトの初期化 の2つがありますが、説明を思いつきませんでした。

どのように解決するのですか?

ここでの問題は、かなり微妙です。 あなたは次のように考えるでしょう。

bar::bar() = default;

を使えば、コンパイラが生成したデフォルトのコンストラクタが得られると思いますし、実際そうなのですが、現在はユーザが提供したものとみなされています。 [dcl.fct.def.default]/5 の状態になります。

明示的にデフォルト化された関数と暗黙的に宣言された関数をまとめてデフォルト化関数と呼び、実装では暗黙的な定義([class.ctor] [class.dtor], [class.copy.ctor], [class.copy.assign] )を提供しなければならず、これは削除したものとして定義するということかもしれません。 関数は、ユーザが宣言し、最初の宣言で明示的にデフォルトまたは削除されていない場合、ユーザが提供するものです。 ユーザが提供した明示的にデフォルトされた関数(すなわち、最初の宣言の後に明示的にデフォルトされた関数)は、明示的にデフォルトされた時点で定義されます。そのような関数が暗黙的にdeletedとして定義されている場合、そのプログラムは不正確な形式となります。[ 注:関数を最初の宣言の後にdefaultedとして宣言することで、効率的な実行と簡潔な定義を実現しつつ、進化するコードベースに対して安定したバイナリインタフェースを実現することができる。- エンドノート ]。

強調

ということは、あなたがデフォルトの bar() をデフォルトにしなかったため、ユーザが提供したものとみなされます。 そのため [dcl.init]/8.2

Tがユーザ提供または削除されたデフォルトコンストラクタを持たない(おそらくcv-qualified)クラス型の場合、オブジェクトはゼロ初期化され、デフォルト初期化のためのセマンティック制約がチェックされ、Tが自明ではないデフォルトコンストラクタを持つ場合、オブジェクトはデフォルト初期化されます。

はもはや適用されず、値の初期化も行われません。 b で初期化するのではなく [dcl.init]/8.1に従って初期化します。

Tが(おそらくcv-qualified)クラス型([class])で、デフォルトコンストラクタ([class.default.ctor])が無いか、デフォルトコンストラクタがユーザ提供または削除されている場合、そのオブジェクトはデフォルト初期化(default-initialized)となります。