C++: Where to Initialize Variables in Constructor

C++: Where to initialize variables in constructor

In short, always prefer initialization lists when possible. 2 reasons:

  • If you do not mention a variable in a class's initialization list, the constructor will default initialize it before entering the body of the constructor you've written. This means that option 2 will lead to each variable being written to twice, once for the default initialization and once for the assignment in the constructor body.

  • Also, as mentioned by mwigdahl and avada in other answers, const members and reference members can only be initialized in an initialization list.

Also note that variables are always initialized on the order they are declared in the class declaration, not in the order they are listed in an initialization list (with proper warnings enabled a compiler will warn you if a list is written out of order). Similarly, destructors will call member destructors in the opposite order, last to first in the class declaration, after the code in your class's destructor has executed.

Do constructors have to initialize member variables in C++?

It really depends on what member variables you have. If you provide a constructor and don't explicitly initialize a variable in the member initialization list, then it will be default initialized. And this is for every variable.

Now, default initialization does something else depending on what variable you have. If you have a builtin type, like int or bool, then it will not be initialized to 0 or any other value, just like if you had:

int value; // it has an indeterminate value

This also applies to arrays. If it is another class, then the default constructor of that class will be called, just like if you had:

struct Foo { /*something*/ };
Foo value; // calls default constructor, i.e. initializes object

Initialization of variables: Directly or in the constructor?

There's one potentially significant difference in some cases.

Instance initializers are executed before the base class constructor is executed. So if the base class constructor invokes any virtual methods which are overridden in the derived class, that method will see the difference. Usually this shouldn't be a noticeable difference, however - as invoking virtual methods in a constructor is almost always a bad idea.

In terms of clarity, if you initialize the variable at the point of declaration, it makes it very clear that the value doesn't depend on any constructor parameters. On the other hand, keeping all the initialization together helps readability too, IMO. I would try to make sure that wherever possible, if you have multiple constructors they all delegate to one "master" constructor which does all the "real" initialization - which means you'll only put those assignments in one place either way.

Sample code to demonstrate the difference:

using System;

class Base
{
public Base()
{
Console.WriteLine(ToString());
}
}

class Derived : Base
{
private int x = 5;
private int y;

public Derived()
{
y = 5;
}

public override string ToString()
{
return string.Format("x={0}, y={1}", x, y);
}
}

class Test
{
static void Main()
{
// Prints x=5, y=0
new Derived();
}
}

Constructor Initialization and private variables set inside constructor

Well yes, you can initialize other member variables in the constructor,
even if it doesn't take the corresponding arguments.

However, in the example you gave above:

WordAnalysis::WordAnalysis(int arrSize){

wordCount = arrSize;
int timesDoubled = 0;
int index = 0;
}

You aren't actually initializing the timesDoubled member variables, because you wrote "int" before it, which is declaring a new variable and setting that to 0.

If you want to set the classes timesDoubled variable you have to write:

timesDoubled = 0;

Or if you want to be more explicit about it, you can even write:

WordAnalysis::timesDoubled = 0;

C++ Constructor with variable initialization

Yes, the code initializes the variables to the values in the parentheses. This feature of C++ is known as initialization lists.

As indicated in the Standard C++ FAQ, when writing class constructors you should prefer using member initialization lists to assignment:

Consider the following constructor that initializes member object x_
using an initialization list: Fred::Fred() : x_(whatever) { }. The
most common benefit of doing this is improved performance. For
example, 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. Even if the types are not the same, the compiler is usually
able to do a better job with initialization lists than with
assignments.

The other (inefficient) way to build constructors is via assignment,
such as: Fred::Fred() { x_ = whatever; }. In this case 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.

As if that wasn’t bad enough, there’s another source of inefficiency
when using assignment in a constructor: the member object will get
fully constructed by its default constructor, and this might, for
example, allocate some default amount of memory or open some default
file. All this work could be for naught if the whatever expression
and/or assignment operator causes the object to close that file and/or
release that memory (e.g., if the default constructor didn’t allocate
a large enough pool of memory or if it opened the wrong file).

Conclusion: All other things being equal, your code will run faster if
you use initialization lists rather than assignment.

In other words, the code as shown is preferable to the alternative code where the class's member variables are initialized in the body of the constructor:

UnorderedArray(int size, int growBy = 1)
{
m_array = NULL;
m_maxSize = 0;
m_growSize = 0;
m_numElements = 0;

if (size) {
m_maxSize = size;
m_array = new T[m_maxSize];

m_growSize = ((growBy > 0) ? growBy : 0);
}
}

Variables initialized in constructor not staying initialized (c++)

The problem is that you aren't returning the object you are initializing with those values. Your call to skew_value constructor taking float arguments constructs and initializes a temporary anonymous automatic skew_value object but doesn't copy it into the object you are supposed to be constructing nor does it modify it. As such the changes aren't reflected in the object ultimately returned.

C++ isn't Java or C# where you can call nested constructors natively this way (from the body of a function).

However...

C++11 introduced this ability; you just aren't using the proper syntax for it. It should be called like an initializer list argument.

You should instead say:

struct skew_value
{
skew_value( float tlX=1, float tlY=0, float trX=0,
float trY=0, float blX=0, float blY=0,
float brX=0, float brY=0)
: skew_value( Vector2f( tlX, tlY ),
Vector2f( trX, trY ),
Vector2f( blX, blY ),
Vector2f( brX, brY ) )
{
}

skew_value(Vector2f topLeft, Vector2f topRight,
Vector2f bottomLeft, Vector2f bottomRight)
{
TLSkew = topLeft;
TRSkew = topRight;
BLSkew = bottomLeft;
BRSkew = bottomRight;

xScale = 1;
yScale = 1;
}
....
}

IF C++11 features can't be used
Then you will have to do it the long way and again it's suggested to use an initializer list to initialize all of your values.

Additional Reference
Find more in this related question which might this might be a duplicate of: Can I call a constructor from another constructor (do constructor chaining) in C++?



Related Topics



Leave a reply



Submit