DasBoot
DasBoot

Reputation: 277

C++ Initialising fields directly vs initialisation list in default constructor

I'd like to know if there is a difference between this code:

class Foo{
 private:
    int a = 0;
 public:
    Foo(){}
}

And:

class Foo{
 private:
    int a;
 public:
    Foo(): a(0) {}
}

And, if so, which should be preferred? I know it's preferable to use an initialiser list than assigning in the constructor body, but what about initialiser list vs directly initialising in field declaration (for primitive types, at least, as is the case here)?

Also, what of the case below:

class Foo{
 private:
   int a = 0;
 public:
   Foo(){}
   Foo(int i): a(i) {}
}

When the non-default constructor is called: is "a" initialised twice, first to 0 then to "i", or directly to "i"?

Upvotes: 26

Views: 6634

Answers (3)

Yakk - Adam Nevraumont
Yakk - Adam Nevraumont

Reputation: 275230

The two are identical.

One rule of software engineering is DRY -- don't repeat yourself. DRY states that if you can avoid repeating the same token twice, or having two identical lists, you should.

This is for a few reasons. Maintaining two identical lists is surprisingly error prone; one gets modified, or has a typo, and the other does not. It makes code longer, which can make it harder to read. And avoiding copy-paste coding encourages using some very powerful and expressive techniques that can make what you are doing clearer than doing it manually 17 times.

struct foo {
  int a;
  foo():a(7) {}
};

here we have repeated ourselves -- the list of member variables, in particular, is listed twice. Once in the definition of foo, and again in the initializer list of foo::foo. If it is missing somewhere, you get uninitialized data.

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

Here we do not repeat ourselves.

struct foo {
  int a = 7;
  foo() {}
  foo(int i):a(i) {}
};

Here there is some repetition, but the repetition is unavoidable. It is, however, minimized.

There is some cost here, because someone might interpret a=7 to mean "it always starts at 7", and not "the default is 7".

struct foo {
  int a = 7;
  foo():a(3) {}
  foo(int i):a(i) {}
};

And the above is a horrible anti-pattern.

Upvotes: 5

Olaf Dietsche
Olaf Dietsche

Reputation: 74018

From cppreference - Non-static data members

Member initialization
1) In the member initializer list of the constructor.
2) Through a default member initializer, which is simply a brace or equals initializer included in the member declaration, which is used if the member is omitted in the member initializer list.

If a member has a default member initializer and also appears in the member initialization list in a constructor, the default member initializer is ignored.


To conclude, both initializers are equivalent and do what they are supposed to do.

I would prefer the default member initializer, if I'd use the default constructor anyway, or if all or most constructors would initialize the member to the same value.

class Foo {
private:
    int a = 0;
};

If all constructors initialize the member to some different value however, using the default member initializer makes less sense, and then an explicit initialization in the respective constructors would be more clear

class Foo {
private:
    int a;
public:
    Foo() : a(3) {}
    Foo(int i) : a(i) {}
};

Upvotes: 18

Sam Varshavchik
Sam Varshavchik

Reputation: 118292

The first set of examples are identical to each other.

For the last example, the C++ standard specifies as follows:

12.6.2 Initializing bases and members

[ ... ]

If a given non-static data member has both a brace-or-equal-initializer and a mem-initializer, the initialization specified by the mem-initializer is performed, and the non-static data member’s brace-or-equal-initializer is ignored. [ Example: Given

struct A {
int i = /∗ some integer expression with side effects ∗/ ;
A(int arg) : i(arg) { }
// ...
};

the A(int) constructor will simply initialize i to the value of arg, and the side effects in i’s brace-or-equal-initializer will not take place. — end example ]

Upvotes: 9

Related Questions