91

I have been working in C++ for some time now, but I am unsure about the difference between the two options:

public : Thing(int _foo, int _bar): member1(_foo), member2(_bar){}

and

public : Thing(int _foo, int _bar){
    member1 = _foo;
    member2 = _bar;
}

I have a feeling that they do the same thing, but is there a practical difference between these 2 syntaxes. Is one of these safer then the other, and do they handle default parameters differently.

Not totally accustomed to the first example so if I made a mistake on it I apologize.

Guy Avraham
  • 3,482
  • 3
  • 38
  • 50
gardian06
  • 1,496
  • 3
  • 20
  • 34

6 Answers6

99

They are not the same if member1 and member2 are non-POD (i.e. non-Plain Old Data) types:

public : Thing(int _foo, int _bar){
    member1 = _foo;
    member2 = _bar;
}

is equivalent to

public : Thing(int _foo, int _bar) : member1(), member2(){
    member1 = _foo;
    member2 = _bar;
}

because they will be initialized before the constructor body starts executing, so basically twice the work is done. That also means, if the type of these members don't have default constructor, then your code will not compile.

eddie
  • 1,252
  • 3
  • 15
  • 20
Luchian Grigore
  • 253,575
  • 64
  • 457
  • 625
  • I have been working with self-made data types, and even when I don't have default constructors, and use my second example I have never gotten any such compiler error on gcc, or VS2008/2010 – gardian06 Mar 28 '12 at 08:17
  • @gardian06 if you have no constructors, the compiler will generate a default one for you. Try adding a constructor with some parameters, and it will fail. – Luchian Grigore Mar 28 '12 at 08:18
  • I mean having a parameterized constructor, but no default, and then using my second example to do work to give a parameter to the constructor of the self-defined object. no error. when making ADTs it is not unheard of to not have a default constructor – gardian06 Mar 28 '12 at 08:22
  • 1
    @gardian06 that doesn't sound right. Do you have a tiny, compilable example? – juanchopanza Mar 28 '12 at 08:27
  • @gardian06 the your compiler is wrong - http://ideone.com/nerKS – Luchian Grigore Mar 28 '12 at 08:27
  • 2
    *twice the work is done*, not really. It is just more work, not twice the work. – Alok Save Mar 28 '12 at 08:29
  • could have sworn I have done this with static members that didn't have default constructors, but the only examples I have use members that are pointers. – gardian06 Mar 28 '12 at 09:05
  • though of my examples if one of the members is of nonconst pointer to type, and other members are static members. is it reasonable to mix these forms assuming that the static members can be set directly from the parameters? – gardian06 Mar 28 '12 at 09:07
  • @gardian06 actually, statics should be initialized separately, not in the constructor, since the constructor creates an instance, while a static is tied to a class. – Luchian Grigore Mar 28 '12 at 09:10
23

The first one is the recommended best practice, as it is more idiomatic and avoids re-initializing fields for types which do have a default constructor (i.e. non-primitive types).

When you only initialize a member inside the constructor body, the compiler generates a default member initialization statement for you if it can, so you end up doubly initializing it. This may not be a big deal in some cases, but may be serious performance overhead if constructing the object is expensive.

Update

However, user defined types without a(n explicitly defined or generated) default constructor can't be initialized this way, so a compiler error is produced. The same is true for const and reference fields - these can only be initialized explicitly in the member initializer list.

Community
  • 1
  • 1
Péter Török
  • 114,404
  • 31
  • 268
  • 329
  • so if I use the second example does that mean that the members are technically being initialized twice, and then what about if a default constructor does not exist for those types – gardian06 Mar 28 '12 at 07:56
  • 2
    Then the compiler is unhappy. Also - initializer list is the only way to initialize `const` fields of object. – Griwes Mar 28 '12 at 07:58
  • @gardian06, yes, if there is a default constructor. Otherwise for primitive types there is no technical difference, but for user defined types a compiler error is produced, as the compiler can't initialize those fields. The same is true for `const` and reference fields - these can only be initialized in the member initializer list. – Péter Török Mar 28 '12 at 07:58
  • so is it possible to combine these 2 methods use the initializer list for const and native types, then do more in depth work in the body? I have only ever seen them used separately – gardian06 Mar 28 '12 at 08:06
  • I have been using user defined types for some time, and have never had a problem with or without a default constructor, and not using the initilizer list. – gardian06 Mar 28 '12 at 08:08
  • @gardian06, this is because the compiler generates one for you if you haven't defined any. Add a constructor with parameters and you will see the error. – Péter Török Mar 28 '12 at 08:23
  • I mean having a parameterized constructor, but no default, and then using my second example to do work to give a parameter to the constructor of the self-defined object. no error. – gardian06 Mar 28 '12 at 08:25
  • @gardian06, what compiler are you using? – Péter Török Mar 28 '12 at 08:30
18

The only thing to add to Péter Török answer is that the Initializer List is the only way to initialize const members of objects, i.e.:

class foo
{
public:

    foo(int value)
        : myConstValue(value)
    {};

    foo()
    {
        myConstValue = 0; // <=== Error! myConstValue is const (RValue), you can't assign!
    };

private:
    const int myConstValue;
}
Community
  • 1
  • 1
PaperBirdMaster
  • 12,806
  • 9
  • 48
  • 94
  • It's because `const` variables can't be changed, and moreover they have to be given an initial value when they are created. Same thing goes for reference types also. – Galaxy Aug 20 '18 at 05:58
6

In your example code, the first one in constructor initialization and second one is assignment inside constructor body.

Constructor initialization list is the best way to do all member initialization because it improves performance.

class A
{
string name;
public:
A(string myname):name(myname) {}
}

In above case compiler will not create a temporary object to do the initialization. However in the following case:

A::A()
{
    name = myname;
}

A separate temporary object is created, and this temporary object is passed to string's assignment operator to assign to name. Then the temporary object is destroyed, which is not quite efficient.

Note: It is mandatory that a reference or a const member must be intialized in a constructor initialization list. They cannot be 'assigned' in the body of the constructor.

Sanish
  • 1,699
  • 1
  • 12
  • 21
2

Apart from other answers, I would like mention that constructor initialization only for initialize member variables.

class Demo
{
    int a;
    int b;
public:
    Demo(int a,int b):a(a),b(b)
    {

    }

};

if we initialize a and b inside constructor it would be self assignment.

  • 1
    Nice one, you can also use `this->a = a;` to distinguish the member variable from the parameter if you wanted to do the assignment inside the body of the constructor. – Galaxy Aug 20 '18 at 06:00
1

First is initialization, using an initializer list and the second is default construction and then assignment. The first one is at least as fast as the second one and is preferable to the second one.

DumbCoder
  • 5,696
  • 3
  • 29
  • 40
  • does using the second one create problems for say not having a default constructor of the types to be initialized? – gardian06 Mar 28 '12 at 07:58
  • Yes it would(unless it is a built in type like an int or something), should get a compiler error if I remember correctly. – DumbCoder Mar 28 '12 at 08:01