Initializing Fields in Constructor - Initializer List VS Constructor Body

Initializing fields in constructor - initializer list vs constructor body

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.

Difference between initializer and default initializer list in c++

The purpose of default initialization list is to initialize the constant variable with in the class.
Because the constant variable is initialized before the object is initialized.

I provide one sample to explain the difference between these two initializations:

 class A
{
private:
const int x;

};

A::A():x(5) //this code works fine
{

}

A::A() //this code is wrong.const variable is not initialized once object
{
x=5;
}

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

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) {}
};

Initializer list vs Constructor assignment vs variable defining

This excerpt has been taken from "Inside the C++ Object Model" by Stanley B. Lippman.

You must use the member initialization list in the following cases in
order for your program to compile:

1. When initializing a reference member

2. When initializing a const member

3. When invoking a base or member class constructor with a set of arguments

4. A few efficiency cases. (Here the program is correct w/o member initialization list)

For points 1-3, member initialization list is a must.

For point 4, it is not compulsory.

For example(point 4), given :

class Word {
String _name;
int _cnt;
public:
// not wrong, just naive ...
Word() {
_name = 0;
_cnt = 0;
}
};

This implementation of the Word constructor initializes _name once, then overrides the initialization with an assignment, resulting in the creation and the destruction of a temporary String object.

A significantly more efficient implementation would have been coded:

// preferred implementation
Word::Word : _name( 0 )
{
_cnt = 0;
}

Due to this optimisation, a lot of people prefer member initialization list, as a default approach to write constructors.

// some insist on this coding style
Word::Word()
: _cnt( 0 ), _name( 0 )
{}

A reasonable question to ask at this point is, what actually happens to the member initialization list?

The compiler iterates over the initialization list, inserting the initializations in the proper order within the constructor prior to any explicit user code.

For example, the previous Word constructor is expanded as follows:

// Pseudo C++ Code
Word::Word( /* this pointer goes here */ )
{
_name.String::String( 0 );
_cnt = 0;
}

Note : The order in which the list entries are set down is determined
by the declaration order of the members within the class declaration,
not the order within the initialization list. In this case, _name is
declared before _cnt in Word and so is placed first.

So coming back to your question :

class B is fine(since you are using primitive datatypes).

class A will generate the same code as class B

As for class C, the default constructor is first called, and then initialization of width and height would happen. This method should be preferred when there are going to be more than 1 constructor, and for each constructor width and height need to be defaulted to your desired values.

However, since the advent of C++11, and use of {} as uniform initialization, a more recommended approach for writing class C would be :

class C
{
public:
int width {500};
int height {300};
};

What is the difference between using initialization lists to initialize fields and initialize them inside the constructor?

A simple way of looking at it is to make connections with local variables:

  1. Using initializer lists is equivalent to this view of local variables:

    int a = 1;
    int b = 2;
  2. The second form, assigning them inside constructor is equivalent to this:

    int a;
    int b;

    a = 1;
    b = 2;

You can see how this can be a problem with const or with objects that don't have a default constructor:

Const members

  1. Ok:

    const int a = 1;
    const int b = 2;
  2. Not ok:

    const int a;
    const int b;
    a = 1;
    b = 2;

Types with deleted or not accessible default constructor

e.g.:

class X {
public:
X() = delete; // default constructor deleted
X(int){}; // constructor with an int parameter
};
  1. Ok:

    X x(1);
  2. Not ok:

    X x;
    x = X(1);

3rd option: In-class member initializers (since c++11)

class A {
public:
const int a = 10;
};

Base/Default Constructor vs Constructor Initialization list

I have two questions, what is the difference between a default/base construct and a construct initialize list?

A default constructor is a constructor that will be invoked when you create an object but don't specify any constructor arguments. For example, all these variables will be initialised by a call to the default constructor:

Complex myComplex1;
Complex myComplex2();
Complex myComplex3{};

Some other constructors do require arguments, so they're not default constructors.

In the implementation of any constructor (whether a default constructor or not) for an object with bases or member variables or constants, you can use an initialisation list to construct/initialise those bases or members.

They look the same to me, here are my examples. Do I have them commented correctly as well as what they are?

You didn't have them commented correctly. A fixed version is:

Complex::Complex()  // default constructor as it does not require args
: real{}, imag{} // initialization list: sets both to 0.0
{ }

Complex::Complex(double inReal, double inImag) // NOT a default constructor
// as it requires arguments
: real(inReal), imag(inImag) // initialisation list
{
// real = inReal; // set in the initialisation list instead
// imag = inImag;
}

The non-default constructor above is invoked when you create an object while specifying matching constructor arguments:

Complex myComplex4(3.1, 2);
Complex myComplex5{-2.3, 2.7};

It's a good idea to preferentially use an initialisation list to construct your bases and set your members: otherwise at best they'll be default initialised then assigned to, which can be less efficient, but for references and constants you simply have to use an initialisation list.


It is possible to create a default constructor with arguments with default values:

Complex(double inReal = 0.0, double inImag = 0.0)
: real(inReal), imag(inImag)
{ }

This single constructor can reasonably replace both the constructors in your code.

What is the difference between constructor and initializer list in Dart?

There is no difference, the result will be the same except that you can take advantage of different type of constructors.

In the case you don't want to expose your variables defined in Point and your mark those as private, the initializer would be a good option.

    class Point {
final num _x;
final num _y;
final num _distanceFromOrigin;

Point(x, y)
: _x = x,
_y = y,
_distanceFromOrigin = sqrt(x * x + y * y);
}

Also take a look to the constructor with optional parameters or factory constructors.

Order of In Class Initialization versus Constructor Initialization List

This is guaranteed by the standard that non-static data members will be initialized in the order of their declarations in the class definition. How they're initialized (via default member initializer or member initializer list) and the order of these initializers don't matter.

[class.base.init]#13.3

(13.3) - Then, non-static data members are initialized in the order they were declared in the class definition (again regardless of the order of the mem-initializers).

[ Note: The declaration order is mandated to ensure that base and member subobjects are destroyed in the reverse order of initialization. — end note ]

That means, the initialization order will always be ptr -> m1 -> m2.

Difference between assigning the values in parameter list and initializer list

Dart constructs objects in two phases: first outside-in and then inside-out.

Initializer lists are executed outside-in (from derived class to base class). After this is done, the object's members should be initialized, the object is considered to be "constructed", and this exists. (That's why you can't use this in a meaningful way in an initializer list; it doesn't exist yet.) (Technically direct member initialization occurs before initializer lists, but I'm lumping them together for simplicity.)

Constructor bodies are then executed inside-out (from base class to derived class).

This approach guarantees that all of the object's members are initialized when the base class constructor body executes, allowing virtual dispatch to occur in the constructor body. (In contrast, C++ constructs objects purely inside-out and disallows virtual dispatch in constructors and destructors. Or contrast to Java where, IIRC, the class mostly defines its own construction order, and the classes are responsible to ensure that any virtual function calls performed by the constructor are safe.)

Without this approach, a Dart constructor body either cannot guarantee safety when executing virtual functions (the Java approach) or must disallow virtual dispatch (the C++ approach).

One consequence of this approach is that final variables can be initialized by initializer lists but not by constructor bodies: when the constructor body executes, all member variables (that aren't late and that aren't nullable) are expected to be initialized already.

Also see:

  • https://stackoverflow.com/a/64548861/ for various differences between the different ways to initialize members and for an example where the different ways matter.
  • Virtual functions in constructors, why do languages differ?


Related Topics



Leave a reply



Submit