-1

When I am using this code, the output changes based on the sequence of declaration of the pointers in class

#include<iostream>
using namespace std;

class myClass{
    int *y,*z,*x;
    public:
        myClass(int a,int b,int c): x(seta(a)),y(setb(b)),z(setc(c)){}
        int* seta(int a){
            cout<<a;
            return (new int(a));
        }
        int* setb(int b){
            cout<<b;
            return (new int(b));
        }
        int* setc(int c){
            cout<<c;
            return (new int(c));
        }
};

int main(){
    myClass m1(1,2,3);
    return 0;
}

But when I am changing the constructor like this

myClass(int a,int b,int c){
  x=seta(a);
  y=setb(b);
  z=setc(c);
}

Then the output is 123 irrespective of the sequence of declaration of the pointers. WHY?

Adrian Maire
  • 14,354
  • 9
  • 45
  • 85
Saptarshi Dey
  • 125
  • 1
  • 7
  • Possible duplicates: https://stackoverflow.com/questions/1774187/is-the-order-of-initialization-guaranteed-by-the-standard, https://stackoverflow.com/questions/2669888/initialization-order-of-class-data-members, and https://stackoverflow.com/questions/12126209/c-data-members-initialization-order-when-using-initialization-list – 1201ProgramAlarm Feb 07 '21 at 17:02

4 Answers4

1

Because the members of a class/struct are ever initialized in the order of declaration.

In you first example, the order of declaration is y, z, x so the order of execution in the initialization list is

y(setb(b))
z(setc(c))
x(seta(a))

and isn't important the order you gave in the initialization list (but, as pointed by Klaus, you could get a warning, from the compiler, in case the order is different).

So you should get 2 3 1

In your second example y, z, x are default inititialized (with undefined values) and then modified executing the body of the constructor following the order of the instructions

x=seta(a);
y=setb(b);
z=setc(c);

so you get 1 2 3, but only because y, z, x are silently initialized without the use of seta() setb() and setc()

max66
  • 65,235
  • 10
  • 71
  • 111
0

Read this on CPPref

The order of member initializers in the list is irrelevant: the actual order of initialization is as follows:

  1. If the constructor is for the most-derived class, virtual bases are initialized in the order in which they appear in depth-first left-to-right traversal of the base class declarations (left-to-right refers to the appearance in base-specifier lists)
  2. Then, direct bases are initialized in left-to-right order as they appear in this class's base-specifier list
  3. Then, non-static data member are initialized in order of declaration in the class definition.
  4. Finally, the body of the constructor is executed

I.e. In the constructor body the order of initialization is executed in the sequence you describe. But in the initialization list, the order is determined by the order they are declared.

JHBonarius
  • 10,824
  • 3
  • 22
  • 41
0

Member initialization is always in the order of declaration of the member variables.

When you do it as calls in the constructor, the order will be the same as the order you do the calls. If you reverse the order of calls then the order will be reversed as well.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
0

In the initializer list of a constructor your variables will be assigned in the order of member declaration. If you write a initializer list which will not fit the order of the initialization, you should get a warning from your compiler.

Your code example generates the following warnings with gcc:

main.cpp: In constructor 'myClass::myClass(int, int, int)':
main.cpp:267:16: warning: 'myClass::x' will be initialized after [-Wreorder]
  267 |     int *y,*z,*x;
      |                ^
main.cpp:267:10: warning:   'int* myClass::y' [-Wreorder]
  267 |     int *y,*z,*x;
      |          ^
main.cpp:269:9: warning:   when initialized here [-Wreorder]
  269 |         myClass(int a,int b,int c): x(seta(a)),y(setb(b)),z(setc(c)){}
      |         ^~~~~~~

If you write your constructor as given in your second code example, the variables will still be initialized in the order of definition, but the initialization is first with a null pointer and after this has happened, it overwrites the already initialized values with the new ones you give in the body of the constructor.

The compiler will optimize the unused default initialization away, as it has no side effects, but you have to understand that assigning variables inside the constructor body is not variable initialization but assigning!

Klaus
  • 24,205
  • 7
  • 58
  • 113