52

Of what I know of benefits of using initialization list is that they provide efficiency when initializing class members which are not build-in. For example,

Fred::Fred() : x_(whatever) { }

is preferable to,

Fred::Fred() { x_ = whatever; }

if x is an object of a custom class. Other than that, this style is used even with built-in types for the sake of consistency.

The most common benefit of doing this is improved performance. If the expression whatever is the same type as member variable x_, the result of the whatever expression is constructed directly inside x_ — the compiler does not make a separate copy of the object.

With the other style, the expression whatever causes a separate, temporary object to be created, and this temporary object is passed into the x_ object's assignment operator. Then that temporary object is destructed at the ;. That's inefficient.

Question
Is there any efficiency gain in the following example with using initialization list. I think there is no gain. The first version calls string's copy constructor and the other calls string's assignment operator (there isn't any temporary thats created). It that correct?

class MyClass
{
public:
    MyClass(string n):name(n) { }
private:
    string name;
};

class MyClass
{
public:
    MyClass(string n)
    {
        name=n;
    }
private:
    string name;
};
Ankur
  • 11,239
  • 22
  • 63
  • 66
  • 17
    The other benefit of initialization lists (if you want to a call it a benefit) is that they're the only way to initialize certain things - base classes using a non-default ctor, const members and reference members. – Michael Burr Oct 21 '09 at 06:12
  • 8
    Also, if you are worried about performance, I would rather used a 'const&' to pass the argument, instead of copying. – Matthieu M. Oct 21 '09 at 06:36
  • 1
    How can you have `Fred::Fred() : x_(whatever)`? Fred takes no arguments. – Jossie Calderon Jun 26 '16 at 14:32
  • it is very easy to see in visual studio 2017 professional edition 'memory view' the memory addresses looks different and thus falsify all wrong assumptions here. In fact, I came to understand that the true purpose of class initialization list is for the `const` and not about speed. – daparic Jul 18 '18 at 21:15

5 Answers5

39

The second version is calling string's default ctor and then string's copy-assignment operator -- there could definitely be (minor) efficiency losses compared to the first one, which directly calls c's copy-ctor (e.g., depending on string's implementation, there might be useless allocation-then-release of some tiny structure). Why not just always use the right way?-)

Alex Martelli
  • 854,459
  • 170
  • 1,222
  • 1,395
  • 2
    True. You should also mention that sometimes, "the right way" is the *only* option you have. If you need to initialize a reference or a const type, or something which doesn't have an assignment operator, you don't have much choice in the matter – jalf Oct 21 '09 at 10:06
  • @jalf true, but not directly applicable to the code the OP gives (only to variants using e.g. `string&` members instead of `string` ones). – Alex Martelli Oct 21 '09 at 14:21
  • 1
    Don't you mean it's calling `string`'s copy constructor, and then its assignment operator? – Jossie Calderon Jun 26 '16 at 16:23
  • This should not be the accepted answer. The primary purpose for class initialization list is mainly for the `const` and wither it is about speed is only accidental. – daparic Jul 18 '18 at 21:18
21

I think the only way to initialize const data members is in the initialization list

Eg. in the header:

class C
{
    C();
private:
    const int x;
    int y;
}

And the in the cpp file:

C::C() :
    x( 10 ),
    y( 10 )
{
    x = 20; // fails
    y = 20;
}
pxb
  • 747
  • 4
  • 14
  • 1
    This should be the accepted answer. The `const` usage here clearly and without doubt the primary unambiguous crystal clear usage that only works when inside a `class initialization list`. – daparic Jul 18 '18 at 21:19
14

Remember that there is a distinct difference between a copy constructor and an assignment operator:

  • the copy ctor constructs a new object using some other instance as a place to get initialization information from.
  • the assignment operator modifies an already existing object that has already been fully constructed (even if it's only by using a default constructor)

So in your second example, some work has already been done to create name by the time that

 name=n;

is reached.

However, it's quite possible (especially in this simple example) that the work done is vanishingly small (probably just zeroing out some data members in the string object) and that the work is optimized away altogether in an optimized build. but it's still considered good form to use initializer lists whenever possible.

Michael Burr
  • 333,147
  • 50
  • 533
  • 760
  • 1
    Very well said. While this is basic, this is something that is very easy to overlook/forget for someone like myself who learned on C and assembly. – It'sPete Jun 26 '13 at 01:44
14

It's a great way to initialize members that :

  • are const
  • don't have a default constructor (it's private)
Maciek
  • 19,435
  • 18
  • 63
  • 87
2

We can also perform the constructor delegation via the initialization list.

Matthieu
  • 4,605
  • 4
  • 40
  • 60