SF.
SF.

Reputation: 14029

Why must initializer list order match member declaration order?

Why does gcc throw a hissy fit if the initializer list order doesn't match variable order in the class?

class myClass
{
public:
   int A;
   int B;
   myClass();
};

myClass::myClass() :
B(1),
A(2)
{}

will result in:

file.h:274: warning: 'myClass::A' will be initialized after
file.h:273: warning:   'int myClass::B
file.cpp:581: warning:   when initialized here

Is there any specific reason why this kind of warning is issued? Are there any risks associated with initializing variables of a class in order different than they are defined within the class?

(note, there is a question which touches the subject, but the answers are pretty much "because it should be so" without giving any rationale as to why it should be ordered, or what's wrong with this being out of order - I'd like to know why such a restriction exists - could someone give an example where it may backfire maybe?)

Upvotes: 28

Views: 13272

Answers (4)

Xijiao Li
Xijiao Li

Reputation: 1

I think it's just a matter of cleaness. The order of the declaration of class members is defined in the class's header file, while the constructor is defined in the .cpp file.

Suppose that you are going to add another constructor for this class, and only by looking at the .cpp file where you have B(1), A(2), you might mistakenly think that B will be initialized before A and thus write somethings wrong (e.g., B(42), A(B)). The warning is to prevent this from the very beginning.

Upvotes: -4

Shafik Yaghmour
Shafik Yaghmour

Reputation: 158449

The warning is indicating that regardless of the order you use in the constructor initialization list the standard requires that non-static data members be initialized in the order they were declared. We can see this by going to the draft C++ standard section 12.6.2 Initializing bases and members paragraph 10 which says:

In a non-delegating constructor, initialization proceeds in the following order:

and includes:

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).

Why does the standard require this? We can find a rationale for this in paper The Evolution of C++: 1985 to 1989 by Bjarne Stroustrup in section 6 it says:

The initialization takes place in the order of declaration in the class with base classes initialized before members,

[...]

The reason for ignoring the order of initializers is to preserve the usual FIFO ordering of constructor and destructor calls. Allowing two constructors to use different orders of initialization of bases and members would constrain implementations to use more dynamic and more expensive strategies

Upvotes: 30

juanchopanza
juanchopanza

Reputation: 227370

The warning is trying to prevent situations where you might be relying on the wrong ordering of the data members. Say you think B is initialized before A, and then you do something like this:

myClass::myClass() :
B(42), A(B) {}

Here, you have undefined behaviour because you are reading from an uninitialized B.

Upvotes: 21

Samuel
Samuel

Reputation: 6490

The order of the initializer list does NOT matter. The declaration of your members in the class header defines the initialization order.

This is by design and required as you could have multiple ctors having totally different init list orders.

So your members will ALWAYS be initialized in the order of declaration.

Upvotes: 4

Related Questions