Why must initializer list order match member declaration order?
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
.
Constructor initialization-list evaluation order
It depends on the order of member variable declaration in the class. So a_
will be the first one, then b_
will be the second one in your example.
Why should I initialize member variables in the order they're declared in?
The reason is because they're initialized in the order they're declared in your class, not the order you initialize them in the constructor and it's warning you that your constructor's order won't be used.
This is to help prevent errors where the initialization of b
depends on a
or vice-versa.
The reason for this ordering is because there is only one destructor, and it has to pick a "reverse order" to destroy the class member. In this case, the simplest solution was to use the order of declaration within the class to make sure that attributes were always destroyed in the correct reverse order.
Is the order of initialization guaranteed by the standard?
I don't have the standard handy right now so I can't quote the section, but structure or class member initialisation always happens in declared order. The order in which members are mentioned in the constructor initialiser list is not relevant.
Gcc has a warning -Wreorder
that warns when the order is different:
-Wreorder (C++ only)
Warn when the order of member initializers given in the code does
not match the order in which they must be executed. For instance:
struct A {
int i;
int j;
A(): j (0), i (1) { }
};
The compiler will rearrange the member initializers for i and j to
match the declaration order of the members, emitting a warning to
that effect. This warning is enabled by -Wall.
Order of member initialization list
Initialization of member variables occurs in the order that they are declared in the class.
http://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Rc-order
and:
http://en.cppreference.com/w/cpp/language/initializer_list
3) Then, non-static data members are initialized in order of
declaration in the class definition.
Order of execution in constructor initialization list
According to ISO/IEC 14882:2003(E) section 12.6.2:
Initialization shall proceed in the following order:
- First, and only for the constructor of the most derived class as described below, virtual base classes shall
be initialized in the order they appear on a depth-first left-to-right traversal of the directed acyclic graph
of base classes, where “left-to-right” is the order of appearance of the base class names in the derived
class base-specifier-list.- Then, direct base classes shall be initialized in declaration order as they appear in the base-specifier-list
(regardless of the order of the mem-initializers).- Then, nonstatic data members shall be initialized in the order they were declared in the class definition
(again regardless of the order of the mem-initializers).- Finally, the body of the constructor is executed.
So, follow that order, and you'll have your order. Also according to the standard, the order is prescribed as such so that objects can be uninitialized in the precisely reverse order.
Constructor initializer list doesn't follow order
Is there any way i can make Base constructor get called after?
No. An object's constructor must construct its base classes before any named member variables.
I'm trying to get rid of all the init methods and their calls by putting them into constructor instead
That is a worthwhile effort!
I'll assume your real code variable
is something more complex than an int
. Because if it's an int, you could simply call Base(50)
.
You can use delagating constructors to prepare a variable before any constructor begins initialization.
class Derived : public Base
{
public:
// Generate an important value FIRST, and then delegate
// construction to a new constructor.
Derived() : Derived( GenerateSomethingComplex() ) {}
private:
// Here, we can honor constructing Base before Derived
// while "some value" has been procured in advance.
Derived( SomethingComplex&& var) :
Base( var ),
variable( std::move(var) )
{}
SomethingComplex variable;
};
Order of Initializer list in C++
class Z {
public:
Z() throw();
protected:
X x_;
Y y_;
};
Z::Z() throw() : y_(), x_(y_) {}
In Z
, you declare x_
before y_
. Therefore, x
is constructed before y_
regardless of the order of your initializers.
And, initializing x_(y_)
before y_
is constructed yields undefined behavior.
I expected above program to give seg fault
Undefined behavior is undefined. You should not expect anything in particular.
Why should I prefer to use member initialization lists?
For POD class members, it makes no difference, it's just a matter of style. For class members which are classes, then it avoids an unnecessary call to a default constructor. Consider:
class A
{
public:
A() { x = 0; }
A(int x_) { x = x_; }
int x;
};
class B
{
public:
B()
{
a.x = 3;
}
private:
A a;
};
In this case, the constructor for B
will call the default constructor for A
, and then initialize a.x
to 3. A better way would be for B
's constructor to directly call A
's constructor in the initializer list:
B()
: a(3)
{
}
This would only call A
's A(int)
constructor and not its default constructor. In this example, the difference is negligible, but imagine if you will that A
's default constructor did more, such as allocating memory or opening files. You wouldn't want to do that unnecessarily.
Furthermore, if a class doesn't have a default constructor, or you have a const
member variable, you must use an initializer list:
class A
{
public:
A(int x_) { x = x_; }
int x;
};
class B
{
public:
B() : a(3), y(2) // 'a' and 'y' MUST be initialized in an initializer list;
{ // it is an error not to do so
}
private:
A a;
const int y;
};
Related Topics
How to Enforce the 'Override' Keyword
Can't Compile Easy Source in C++ and Opengl (Glfw) in Linux in Netbeans
Iterator Adapter to Iterate Just the Values in a Map
_Attribute_((Format(Printf, 1, 2))) for Msvc
How to Set the Cout Locale to Insert Commas as Thousands Separators
Skip Some Arguments in a C++ Function
Character Pointers and Integer Pointers (++)
Ordering of Using Namespace Std; and Includes
Undefined Reference to a Static Member of the Class
C++ Multi-Line Comments Using Backslash
How to Implement a Map with Different Data Types as Values
How to Convert "Pointer to Pointer Type" to Const
Strange "Unsigned Long Long Int" Behaviour