Why is initialization preferred to assignment?

I know this is not a new feature of C++11 but it has been enhanced.
And I've never quite understood the reasoning. It seems that it
is preferable to use initialisation in a Constructor rather
than assignment:

1
2
3
4
5
6
class C{
private:
   int n;
public:
   C(int j): n{j}{};
};


Rather than
1
2
3
4
5
6
class C{
private:
   int n;
public:
   C(int j){n=j;};
};


Why is the former better? To me it just seems to add yet more
syntactic clutter for no obvious benefit.
Last edited on
EDIT: The best I can figure is that even though your assignment is in a class header, the variable n still does not equal j until run-time.

With initialization, the variable equals j at compile-time.
--[Thank you JLBorges].

There are some equations that can be done at compile time that might exponentially speed up program execution by putting the stress on the compiler ( https://en.wikipedia.org/wiki/Memoization ), and initializing the variable might make it usable at compile-time if needed.

Memoization: cheating by knowing the answer before the question is asked.
Last edited on
The reason is simple. In the first example only the constructor is called. In the second example if n had a construct it is called first then the content is changed.

This saves processor time: One action in place of two.
Last edited on
Sorry #coder777, I'm still not getting it. If n had a constructor surely it would still need to be called in both cases?

#newbleg, I'll need to look into the limitations of initialization but memoization might be a valid use-case if initialization is limited to compile time expressions only. Although in that case wouldn't it limit the values that can be passed to the constructor by user code? ie How would the compiler be able to predict the values passed in other, separately compiled, modules?
For a member object with trivial initialisation (eg. int), there is no performance difference between direct initialisation and do-nothing-initialisation followed by assignment. In this case, the only advantage of initialisation over assignment is that it prevents 'use-before-giving-it-a-value' errors.

For member objects with non-trivial initialisation, there could be a performance impact. Constructing an object in a specific state is usually cheaper than default constructing the object and then following it up with assigning to the already constructed object.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include <iostream>

struct A
{
    int value ;
    explicit A( int v = 0 ) { value = v ; std::cout << "A::constructor, " ; }
    A& operator= ( int v ) { value = v ; std::cout << "A::assignment\n" ; return *this ; }
};

struct B1
{
    A a ;
    explicit B1( int v ) : a{v} { std::cout << "body of B1::constructor\n" ; }
};

struct B2
{
    A a ;
    explicit B2( int v ) { std::cout << "body of B2::constructor, " ; a = v ; }
};

int main()
{
    B1 b1{7} ; // A::constructor, body of B1::constructor

    B2 b2{7} ; // A::constructor, body of B2::constructor, A::assignment
}

http://coliru.stacked-crooked.com/a/ad4fa5815cbba73c


> With initialization, the variable equals j at compile-time.

No. That is guaranteed to be the case only if
1. the constructor is constexpr
and 2. the value passed to the constructor is a constant known at compile time.
Last edited on
If n had a constructor surely it would still need to be called in both cases?
Yes, that's true, but in the second example additionally the operator= is called.
Ah, OK now I begin to see the logic. I'll need to do a few more experiments but that's starting to make sense.
OK, Experiments complete and I think I get it now.

Basically it only really matters when the members are classes.

The issue is that the member constructors are called before the outer class constructor so if you try to use assignment you do two operations on the member instead of one. Also for const and reference members as well as copy constructors its the only way to properly construct the members.

So in summary: using initialisation rather than assignment is more efficient, guarantees copy constructors get called and is the only way to initialize const and reference members. And since there is no performance penalty you might ass well use it for non class members too.

If I've got that wrong please shout.
One thing to bear in mind while using member initialization lists is the initialization order of class/struct data members: http://stackoverflow.com/questions/2669888/c-initialization-order-of-class-data-members

example: http://coliru.stacked-crooked.com/a/08ca1fa7654d00aa

... you might ass well use it for non class members too.

what do you mean by 'non class members'?
CoreGuidelines:

Don't define a default constructor that only initializes data members; use member initializers instead
https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#Rc-default

Define and initialize member variables in the order of member declaration
https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#Rc-order

Prefer in-class initializers to member initializers in constructors for constant initializers
https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#Rc-in-class-initializer

Prefer initialization to assignment in constructors
https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#Rc-initialize
#gunnerfunner: By "non class member" I meant a member which was not a class - basically a built in type.
Topic archived. No new replies allowed.