C ++構造体のメンバーはデフォルトで0に初期化されていますか?


200

私はこれを持っていますstruct

struct Snapshot
{
    double x; 
    int y;
};

私は0 になりたいxと思っyています。デフォルトで0になるのでしょうか。

Snapshot s = {0,0};

構造をゼロにする他の方法は何ですか?


std :: map <>を使用し、キーが存在しない場合は0を返します。
ジョニー

回答:


263

構造体を初期化しない場合、これらはnullではありません。

Snapshot s; // receives no initialization
Snapshot s = {}; // value initializes all members

2番目はすべてのメンバーをゼロにし、最初のメンバーは指定されていない値のままにします。再帰的であることに注意してください:

struct Parent { Snapshot s; };
Parent p; // receives no initialization
Parent p = {}; // value initializes all members

2番目はp.s.{x,y}ゼロになります。構造体にコンストラクターがある場合、これらの集約初期化子リストは使用できません。その場合は、これらのコンストラクターに適切な初期化を追加する必要があります

struct Snapshot {
    int x;
    double y;
    Snapshot():x(0),y(0) { }
    // other ctors / functions...
};

xとyの両方を0 x(), y()に初期化します。これらを使用して、タイプに関係なくそれらを初期化できることに注意してください。これが値の初期化であり、通常は適切な初期値(intの場合は0、doubleの場合は0.0、ユーザー定義のデフォルトコンストラクターを呼び出します)ユーザーが宣言したコンストラクタを持つ型、...)。これは、構造体がテンプレートの場合は特に重要です。


1
これは私のコンパイラでたくさんの警告を出します。
River-Claireウィリアムソン

1
ロジャー:名前付き構造体をイニシャライザーで使用してみてください。それが私が行うことであり、VC 2012で警告が表示されません。スナップショットs = Snapshot();
キット

@Johannes Schaub-litb Snapshot s = {};非PODメンバー(ゼロ化)で機能しますか?
ontherocks 2013年

2
C ++ 11では、次のように、構造体またはクラスの定義でそれらを初期化できるようになりました。struct Snapshot {double x {0}; //中かっこでint y = 0; //または単に「初期化」でもある「割り当てによる」古いスタイルのみ};
ikku100 2016

1
「スナップショットs = {};」です 標準の一部ですか?
ステファン

40

いいえ、デフォルトでは0ではありません。すべての値またはデフォルトが0であることを確認する最も簡単な方法は、コンストラクターを定義することです。

Snapshot() : x(0), y(0) {
}

これにより、スナップショットのすべての使用で初期化された値が確保されます。


24
欠点は、コンストラクターがあるため、構造体がPODタイプではなくなったことです。これにより、一時ファイルへの書き込みなどの一部の操作が中断されます。
finnw 2009

16
@finnw:C ++ 11はこれを修正します。構造体はPODではありませんが、「標準レイアウト」です。
Ben Voigt

19

一般的には違います。ただし、/スコープ/関数でファイルスコープまたは静的として宣言された構造体は、(これらのスコープの他のすべての変数と同様に)0に初期化されます。

int x; // 0
int y = 42; // 42
struct { int a, b; } foo; // 0, 0

void foo() {
  struct { int a, b; } bar; // undefined
  static struct { int c, d; } quux; // 0, 0
}

1
それは本当に安全な仮定ではありません。初期化していないものの値に依存しないでください
Hasturkun

24
静的ストレージ期間オブジェクトは常にゼロに初期化されます- 標準からの引用については、stackoverflow.com / questions / 60653 /…を参照してください。これが良いスタイルかどうかは別問題です。
bdonlan 2009

12

PODを使用すると、次のように書くこともできます。

Snapshot s = {};

C ++ではmemsetを使用しないでください。memsetには、構造体に非PODがある場合、破壊されるという欠点があります。

またはこのように:

struct init
{
  template <typename T>
  operator T * ()
  {
    return new T();
  }
};

Snapshot* s = init();

あぁぁぁぁぁぁぁぁぁぁぁぁぁぁぁぁ
Ben Sinclair

@AndyほとんどのVexing Parse SomeType foo();は、通常のctorのように見えるもの(他のものでも発生する可能性fooがありますSomeType)を関数定義(その場合、を返す関数)に変換します。ネクロは申し訳ありませんが、誰かがこれに遭遇した場合は、私が答えると思いました。
モニカの訴訟に資金

7

C ++では、引数のないコンストラクターを使用します。Cではコンストラクターを使用できないため、memsetまたは興味深いソリューション-指定された初期化子を使用します。

struct Snapshot s = { .x = 0.0, .y = 0.0 };

これはC ++ではなくCだと思います。一部のC ++コンパイラではコンパイルに失敗します。CygwinまたはMinGWでコンパイルエラーが発生しました。
jww 2015

3

正解は、それらの値は未定義であると考えています。多くの場合、デバッグバージョンのコードを実行すると、これらは0に初期化されます。これは通常、リリースバージョンを実行している場合には当てはまりません。


2
実際、デバッグバージョン0は、メモリ内のこれらの場所にすでに存在します。これは初期化と同じではありません!
オービットのライトネスレース

3

これはPOD(基本的にはC構造体)なので、Cの方法で初期化しても害はほとんどありません。

Snapshot s;
memset(&s, 0, sizeof (s));

または同様に

Snapshot *sp = new Snapshot;
memset(sp, 0, sizeof (*sp));

calloc()ただし、C ++プログラムで使用することはできません。


3
ダブルについても同じことが言えます。all-bits-zeroは必ずしも0.0ではありません。ただし、IEEE754ダブルを使用しているかどうかを確認できます。この場合、IEEE754が機能する必要があります。
MSalters 2009

1

ポッドメンバーを基本クラスに移動して、初​​期化子リストを短くします。

struct foo_pod
{
    int x;
    int y;
    int z;
};

struct foo : foo_pod
{
    std::string name;
    foo(std::string name)
        : foo_pod()
        , name(name)
    {
    }
};

int main()
{
    foo f("bar");
    printf("%d %d %d %s\n", f.x, f.y, f.z, f.name.c_str());
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.