55

I have the following class definitions in c++:

struct Foo {
  int x;
  char array[24];
  short* y;
};

class Bar {
  Bar();

  int x;
  Foo foo;
};

and would like to initialize the "foo" struct (with all its members) to zero in the initializer of the Bar class. Can this be done this way:

Bar::Bar()
  : foo(),
    x(8) {
}

... ?

Or what exactly does the foo(x) do in the initializer list?

Or is the struct even initialized automatically to zero from the compiler?

Jan Rüegg
  • 9,587
  • 8
  • 63
  • 105
  • 4
    Note that members should be listed on initialization list in the same order as they are declared, while you declare `x` first but have it second on initialization list. – Adam Badura Nov 17 '10 at 09:52

2 Answers2

55

First of all, you should (must !) read this c++ faq regarding POD and aggregates. In your case, Foo is indeed a POD class and foo() is a value initialization :

To value-initialize an object of type T means:

  • if T is a class type (clause 9) with a user-declared constructor (12.1), then the default constructor
    for T is called (and the initialization is ill-formed if T has no accessible default constructor);
  • if T is a non-union class type without a user-declared constructor, then every non-static data member and base-class component of T is value-initialized;
  • if T is an array type, then each element is value-initialized;
  • otherwise, the object is zero-initialized

So yes, foo will be zero-initialized. Note that if you removed this initialization from Bar constructor, foo would only be default-initialized :

If no initializer is specified for an object, and the object is of (possibly cv-qualified) non-POD class type (or array thereof), the object shall be default-initialized; if the object is of const-qualified type, the underlying class type shall have a user-declared default constructor. Otherwise, if no initializer is specified for a nonstatic object, the object and its subobjects, if any, have an indeterminate initial value;

Community
  • 1
  • 1
icecrime
  • 74,451
  • 13
  • 99
  • 111
10

In standard C++ you need to make a ctor for Foo.

struct Foo {

  Foo(int const a, std::initializer_list<char> const b, short* c)
    : x(a), y(c) {
    assert(b.size() >= 24, "err");
    std::copy(b.begin(), b.begin() + 24, array);
  }

  ~Foo() { delete y; }

  int x;
  char array[24];
  short* y;
};

class Bar {

  Bar() : x(5), foo(5, {'a', 'b', ..., 'y', 'z'},
    new short(5)) { }

  private:

  int x;
  Foo foo;
};

In C++0x you may use uniform initialization list, but still you need dtor for Foo:

class Bar {

  Bar() : x(5), foo{5, new char[24]{'a', 'b', ..., 'y', 'z'},
    new short(5)} { }
  ~Bar() { delete[] foo.array; delete foo.y;}
  }
  private:

  int x;
  Foo foo;
};

To default initialize foo (as Bar() : foo(), x(8) { }) you need to give Foo a default ctor.

erjot
  • 1,362
  • 1
  • 9
  • 13
  • 3
    This is a bit unclear where you use C++03 vs C++0x. IIRC `initializer_list` is part of c++0x. Besides in your second codeblock you created two memory leaks. – Fabio Fracassi Nov 17 '10 at 10:14
  • now you have one double deletion (`foo.y`) and one memory leak (from the `new char[24]`, besides, I am not sure (but I might be wrong here) that this is the way to use `initializer_list`) – Fabio Fracassi Nov 17 '10 at 19:03
  • Had similar case, but `struct Foo {int x,y; }`, `struct Goo : Foo { int z; }`, `struct Boo { Foo fs[2]; int x; }` and static const array of Boos with initializer list `static const Boo boos[] = { {{foo1, foo2},11}, {{foo3, foo6},15} }` Dilemma to init like this: `struct Goo(int x, int y) : Foo(x,y)`, I'd need a ctor for Foo, but can not use non-aggregate (ctor) in initializer list... – slyy2048 Feb 25 '16 at 19:25