12

Is there any benefit to putting a class member variable in an initializer list that doesn't need to be in an initializer list? Example:

class Foo
{
public:
  Foo() {}
};

class Bar
{
public:
  Bar() : _foo() {}

private:
  Foo _foo;
};

Does the compiler do anything special, in this case?

Wolf
  • 9,679
  • 7
  • 62
  • 108
MarkP
  • 4,168
  • 10
  • 43
  • 84
  • `_foo` is already initialize (using foo's default constructor) from the declaration `Foo _foo;` If you want to re-inisialize `_foo` use `Bar() : _foo(Foo()) {}`. However, this would be pointless. – andre Nov 05 '12 at 18:41
  • 6
    @ahenderson: That's not correct. `_foo` is initialized in the initializer list. That is the one and only place where members are initialized in a class. `Bar() : _foo(Foo()) {}` doesn't *re-initialize* `_foo` -- it **initializes** it. – John Dibling Nov 05 '12 at 18:55
  • @JohnDibling oh, I was mistaken then. I understand now from reading Kerrek SB answer. – andre Nov 05 '12 at 19:01

4 Answers4

14

In this case it makes no difference.

But it can be useful to do so.
If you have a large number of members then having some but not all members in the list can cause some confusion. Also it reinforces in your mind the order of initialization (the order is defined by the order of declaration in the class, but it can be useful to visualize this order in larger classes where not all the member variables are declared beside each other).

Note: If you put them in the wrong order in the internalizer list this is usually just a warning on most compilers (unless you compile with warnings as errors (which you should)).

The real danger is with classes that have a POD members and compiler generated constructor.

class NewFoo
{
      int x;
      int y;
};
// Version 1:
class Bar1
{
     NewFoo  f;
};
// Version 2:
class Bar2
{
     NewFoo  f;
     public:
         Bar2()  // f not in list.
         {}
};
// Version 3:
class Bar3
{
     NewFoo  f;
     public:
         Bar3()
            : f()
         {}
};

int main()
{
     Bar1     b1a;           // x and y not  initialized.
     Bar1     b1b = Bar1();  // x and y zero initialized.
     Bar2     b2a;           // x and y not  initialized.
     Bar2     b2b = Bar2();  // x and y not  initialized.
     Bar3     b3a;           // x and y zero initialized.
     Bar3     b3b = Bar3();  // x and y zero initialized.
}
Martin York
  • 257,169
  • 86
  • 333
  • 562
  • 1
    +1 for this real answer. I'm following the style you advice for years, but now I'm wondering if the trivial repetition of members can also be just "noise". For structure-like classes that have only members with default constructors, wouldn't it be better to use an empty initializer list? – Wolf Apr 04 '14 at 10:19
  • @Wolf: Yes. This is all contextual. You should use the technique that makes the code easier to read. If it is obvious that your class has members that are auto constructed then it is fine just to have an empty list. – Martin York Apr 04 '14 at 14:12
  • @Wolf: Updated answer with info. – Martin York Apr 04 '14 at 14:23
  • `Bar3(): f() {}` - this does nothing with my compiler (x, y are undefined) - is this a C++11 feature? – Wolf Apr 04 '14 at 14:32
  • @Wolf: No this is a C++03 feature. because you explicitly call the initializer of f. This will call the zero initializing version of the compiler generated constructor. Why do you think they are doing nothing? Which compiler are you using? – Martin York Apr 04 '14 at 14:35
  • The C++03 behaviour makes absolutely sense. I mostly (and hate to) use the BCB6 compiler (Borland C++ 5.6.4), and it has [obviously some flaws at initializer lists](http://stackoverflow.com/q/19905686/2932052) ;) – Wolf Apr 04 '14 at 14:44
  • I run this example in Visual C++ 2013, and in none of the cases are x or y zeroed. So is this a non-conformance of VC++? – Peter B Aug 13 '15 at 10:57
  • In Visual Studio 2017 it works as denoted in the comments. Thanks for the example. – Jarek C Feb 20 '19 at 04:59
9

An initializer list is the preferred way to initialize the members in a constructor. It is the only possible way to initialize reference members and constant members.

Also by using an initializer list, you reduce the chances of accidentally using the variable before it has been initialized. It's part of the larger philosophy of never defining a variable without initializing it.

Syntactic Fructose
  • 18,936
  • 23
  • 91
  • 177
  • 1
    It should be noted that the list should be in the same order as the declarations. It is good practice. – Ed Heal Nov 05 '12 at 18:55
  • reference and constant members can be initialized using in-class initialization (C++11). And for the types in question the initializer list has no effect on whether a member can be accessed before it's initialized; the member is default initialized at the same time in both cases. – bames53 Nov 05 '12 at 19:00
  • 3
    @EdHeal, It's a bit more than good practice. They are initialized in that order, so if you initialize one based off of another, you'd better put the dependent one after the independent one in the class. – chris Nov 05 '12 at 19:19
  • @chris - Yes I know - Just wanted to make the pill sweet. Scott Myers. Cannot remember the number in the first book off the top of my head. – Ed Heal Nov 05 '12 at 19:40
7

Members that are not mentioned in the initializer list of the constructor which is being used are default-initialized. For Foo this means that the default constructor will be called.

The difference between Bar() : _foo() { } and not giving Bar an explicit default constructor at all (or saying Bar() = default is that your version doesn't have a trivial default constructor. Thus the values of std::is_trivially_constructible<Bar>::value will differ from if you left the construc­tor out altogether, though the behaviour is otherwise the same.

Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
  • 1
    I would guess that the question is on the difference between a user provided constructor with and without an initializer in the initializer list for the member in question, not on the difference between a user provided constructor and a non-user provided constructor. – bames53 Nov 05 '12 at 18:52
1

No, nothing different is done in this case. I don't see any benefit to doing this.

bames53
  • 86,085
  • 15
  • 179
  • 244
  • 1
    The benefit is that you don't confuse people who have been trained to look for initializer lists. – Cubic Nov 05 '12 at 18:45