Order of execution in constructor initialization list - c++

Is order of execution in constructor initialization list determinable? I know that members order in a class is the order in which those members will be initialized but if I have scenario like this:
class X()
{
X_Implementation* impl_;
};
and then providing that allocator is available:
X::X():impl_(Allocate(sizeof(X_Implementation)))//HERE I'M ALLOCATING <--1
,impl_(Construct<X_Implementation>(impl_))//AND HERE I'M CONSTRUCTING <--2
{
}
but in order for this to be dependable this order MUST be from left to right. Is it guarantied by GREAT BOOK OF std:: or not? If not I can always move the second line into the body.

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.

The C++ standard does guarantee an order for initialization lists (ISO C++ Standard 12.6.2/5):
...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).
(See Wyatt Anderson's answer for more information.)
Example:
class Foo
{
public:
Foo();
private:
A a;
B b;
C c;
};
Foo::Foo() : b(), a(), c() {
// a is initialized first, then b, then c - NOT b, a, then c!
}
However, you can't initialize a variable twice - what you have won't compile.
class X //() what's with the pair of parentheses you have in your code snippet?
{
public:
X();
private:
X_Implementation* impl_;
};
X::X():
impl_(Allocate(sizeof(X_Implementation))),
// It is not allowed to initialize a data member twice!
impl_(Construct<X_Implementation>(impl_)) {
}
Instead, just put the extra work into the constructor:
X::X() : impl_(Allocate(sizeof(X_Implementation))) {
impl_ = Construct<X_Implementation>(impl_);
}
There may be exception safety issues with the above code, but without knowing what Allocate() or Construct() actually does I'm not able to tell. I can tell you that it's best to separate allocation and construction into their own classes if you do that, using the Resource Acquisition Is Initialization (RAII) idiom:
class XBase
{
protected:
XBase() : impl_(Allocate(sizeof(X_Implementation))) { }
~XBase() {
if( !impl_) { Deallocate(impl_); } // Or something like this
}
X_Implementation* impl_;
};
class X : private XBase // XBase is an implementation detail
{
public:
X() {
impl_ = Construct<X_Implementation>(impl_);
}
~X() {
Destruct<X_Implementation>(impl_); // Or something like this
}
};
This way, if Construct() throws an exception, you won't leak memory since the base class destructor will be called which will deallocate the memory pointed by impl_. This is important because if the exception is not caught and leaves the constructor, its matching destructor will not be called. See Bjarne Stroustrup's paper on exception safety.

Your specific scenario is based on the idea of initializing the same member more than once. This is plain illegal in C++. Your code will not compile. So, the question you are asking doesn't really exist.
The order of member initialization is the order of their declaration in class definition. In no-inheritance contexts that covers everything related to the order of initialization in the constructions initializer list.

Related

I'm confused about this C++ constructor

I tried searching for an answer, but not sure exactly the best terms to use to describe this...
I am reading a book on SFML programming, and one of the examples has me confused with the usage of the constructor.
Lets say we have class A and class B. Class A has a member variable of type B (memberB). The constructor for A looks like:
A::A() : OtherMemberType(with, params), memberB()
{...}
Given that memberB is being initialized with the default constructor in the initialization list, what is the purpose of explicitly listing it in the list? Wouldn't the same effect be had without including it in the list?
Thanks
EDIT: Thanks for the answers. I have now learned the (basic) difference of value-initialization vs. default-initialization.
For more context, since the idea of "class B may be broken was brought up", here is the code example from the text SFML Game Development:
class Game
{
public:Game();
void run();
private:
void processEvents();
void update();
void render();
private:
sf::RenderWindow mWindow;
sf::CircleShape mPlayer;
};
Game::Game()
: mWindow(sf::VideoMode(640, 480), "SFML Application")
, mPlayer()
{
mPlayer.setRadius(40.f);
mPlayer.setPosition(100.f, 100.f);
mPlayer.setFillColor(sf::Color::Cyan);
}
So with that context, does anyone know some of the specifics of SFML? Is sf::CircleShape "broken", or is this a redundant call to the default constructor?
Adam
Initializing the member in the initializer list value-initializes it. Omitting it from the list default-initializes it,
If B is a non-aggregate and has a default constructor, there is no difference.
If B is an aggregate, then there may be a difference. default-initializing it means if it contains built-ins these may not get initialized. value-initializing it would eventually have the effect of zero-initializing its members.
This is an example where the semantics of the initialization would be different:
struct B
{
int i, j, k;
};
struct A
{
A() : b() {} // value-initializes b: b.i, b.j, b.k zero initialized
B b;
};
struct AA
{
AA() {} // default-initializes b: b.i, b.j, b.k have no initialization
B b;
};
By including it in the initialiser list, the member is value-initialised. If it weren't, it would be default-initialised. Whether there's a difference depends on the type.
If it's a class type with a declared default constructor, then there's no difference: that constructor will be used in either case.
Otherwise, value-initialisation will zero-initialise primitive types (and primitive members of class types), while in some circumstances default-initialisation will leave them uninitialised, with an indeterminate value.
UPDATE: In your specific case, the class does have a default constructor, so the explicit initialisation is redundant. But redundancy isn't necessarily a bad thing - it indicates that it's being deliberately value-initialised, not just forgotten about.
Given what mike and juan have said, I'd say that class B's implementation is broken iff it requires to be value-initialized like that unless it'd be reasonably expected to behave that way.
Generally, given a properly designed class - with a user-provided default constructor iff if has POD members - there should be no difference in behavior between value- and default-initializing the member of type B.
Some special classes may not perform zero-initialization of their members and they may lack a default constructor. std::array is one such class. They attempt to retain the performance of the raw type underlying their implementation. Members of such classes will require the value initialization.
There are several possibilities:
Class B is has the usual behavior the value initialization is superfluous. Specifically:
a) class B has no POD-typed members, and the non-POD typed member types are all implemented in line with possibility #1, or
b) class B's user-written default constructor initializes all POD-typed members as appropriate.
Class B has the semantics of a performance-optimized type, such as a numerical type or a replacement for raw C arrays. It lacks a default constructor and won't initialize unless you perform value initialization. Example: std::array<T> where T is POD.
Class B is a template parameter. In absence of any constraints on B, the value initialization is the only safe choice. B could be std::array, after all.
Class B is broken. Its members will be properly initialized if its instances are value-initialized. It needs to be fixed.

Are the C++ member classes constructed before parent classes? [duplicate]

This question already has answers here:
C++: Construction and initialization order guarantees
(5 answers)
Closed 8 years ago.
In the scenario:
class A : public B {
private:
C m_C;
public:
A();
}
is
A::A() :
m_C(5),
B(m_C)
{}
legal? Would B::B(m_C) be invoked after C::C(int)? If so, what should I do to avoid it?
How did this came about in practice:
class MyValidator : public QRegExpValidator {
private:
QRegExp myRegExp;
public:
MyValidator();
virtual void fixup(QString &f);
}
MyValidator::MyValidator()
QRegExpValidator(QRegExp("foo"));
{}
void MyValidator::fixup(QString &f){
// A QRegExp("foo") is also needed here.
}
I already discovered the
const QRegExp & QRegExpValidator::regExp() const;
Which alleviates the need to keep my own reference to myRegExp, so my particular problem is solved..
what remains, is what would be the best pattern if QRegExpValidator did not have such feature to retrieve it's initializer.. manually plumbing all the functions to a member class, instead of inheritance?
This is what the C++11 Standard has to say ([class.base.init]/10):
In a non-delegating constructor, initialization proceeds in the following order:
— First, and only for the constructor of the most derived class (1.8), virtual base classes are 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 classes in the derived class base-specifier-list.
— Then, direct base classes are initialized in declaration order as they appear in the base-specifier-list (regardless of the order of the mem-initializers).
— 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).
— Finally, the compound-statement of the constructor body is executed.
[ Note: The declaration order is mandated to ensure that base and member subobjects are destroyed in the reverse order of initialization. — end note ]
So, the base class is initialized before non-static data members. Your code may invoke undefined behavior if it actually uses the uninitialized data in any way.
In comments, we discussed one possible solution to your design problem is to use has-a rather than is-a. You worried that has-a would violate DRY (don't repeat yourself).
There are two ways I use to avoid WET (write everything (at least) twice) when using has-a. One is using conversion operators that allow your object to be passed to a function expecting your "derived" type. The other is using a delegation operator.
class Object { /* ... */ };
class FakeDerivedObject {
Foo foo;
Object obj;
//...
// conversions
operator Object & () { return obj; }
operator const Object & () const { return obj; }
operator Object * () { return &obj; }
operator const Object * () const { return &obj; }
// delegation
Object * operator -> () { return &obj; }
const Object * operator -> () const { return &obj; }
};
This way, you do not have to "re-implement" the interface of the underlying object.
FakeDerivedObject d;
d->SomeMethodOfUnderlyingObject();
SomeFunctionThatExpectsUnderlyingObject(d);
Is
A::A() : m_C(5), B(m_C) {}
legal?
Yes. You can list initializers in any order you choose.
Would B::B(m_C) be invoked after C::C(int)
No. The compiler will ignore the order you listed the initializers, and initialize bases first in the order they are listed in the class declaration, followed by members in the order they are declared in the class declaration.
Note that most compilers have a warning level which will warn you when initializers are listed in an order other than that matching how the initializers will actually be invoked. According to some coding standards, it is required to list the initializers in the order in which they will be invoked.
Example:
class Base {
public:
Base(){}
};
class Derived: public Base {
public:
Derived();
private:
int _v1;
int _v2;
};
The construction order will be ever Base --> _v1 --> _v2

Does the order of base-class initializers and member variable initializers matter?

Is the order of the initializers for a class' constructor significant?
So say I have:
class MyClass : BaseClass
{
int a, b, c;
public:
MyClass(int);
}
e.g. 1:
MyClass::MyClass(int forBase) :
a(7),
b(14),
c(28),
BaseClass(forBase) { }
e.g. 2:
MyClass::MyClass(int forBase) :
BaseClass(forBase),
a(7),
b(14),
c(28) { }
Would example 1 do something different to example 2?
Would example 1 do something different to example 2?
No. Initialisation order is dictated by the standard, not by the order in which you write the initialisers:
[C++11: 12.6.2/10]: In a non-delegating constructor, initialization
proceeds in the following order:
First, and only for the constructor of the most derived class (1.8), virtual base classes are 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 classes in the derived class base-specifier-list.
Then, direct base classes are initialized in declaration order as they appear in the base-specifier-list (regardless of the order of the mem-initializers).
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).
Finally, the compound-statement of the constructor body is executed.
In fact, if you write them in any other order and one depends on the other, you may well be warned about it:
struct T {
std::vector<int> v;
int w;
T(int w) : w(w), v(0, w) {}
};
int main() {
T t(3);
}
// g++ 4.1.2:
// t.cpp: In constructor 'T::T(int)':
// Line 3: warning: 'T::w' will be initialized after
// Line 2: warning: '__gnu_debug_def::vector<int, std::allocator<int> > T::v'
// Line 5: warning: when initialized here
The order does not matter for the compiler (the initialization order is always base classes first, and always base classes in the order of derivation, and members in the order of declaration), but it does matter for the reader: It is very confusing if the order in which you give the initializers does not match the order in which they are executed. While in most cases it doesn't matter, in some cases you can create subtle bugs, e.g.
struct Derived: Base
{
int member;
Derived();
}
Derived::Derived():
member(3),
Base(member) // This is executed *before* member is initialized!
{
}
This bug would stand out more clearly if the initializers were given in the correct order:
Derived::Derived():
Base(member), // Now we see immediately that member is uninitialized
member(3),
{
}
It doesn't matter in which order you list the initializers in the constructor initialization list. Members are initialized in the order they are declared and base(s) are initialized before members.
However, listing initializers in a different order that that can bite you if a subobject's initial value depends on the values of other subobjects.
class A
{
int y, x;
A(int x_value): x(x_value), y(x) {}
};
Since y is initialized before x, it gets a garbage value, and the order of the initializer list just hides the bug. That's why this deserves a compiler warning.

Class component order of initialisation

class D: A
{
B obj;
C obj2;
}
What order of construction here is guaranteed?
I know that D will be constructed after A, B and C, but what I really want to know is whether A is guaranteed to be constructed before B or C, or even whether B is guaranteed to be constructed before C.
I know you can have an explicit initialiser list:
D(): A(), B(), C()
{}
but does that initialiser list determine the order of initialisation?
Also, does whether or not any of the components do or don't have a default constructor?
From the C++03 standard ISO/IEC 14882:2003(E) §12.6.2/5 [class.base.init]:
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.
[Note: the declaration order is mandated to ensure that base and member subobjects are destroyed in the reverse order of initialization. ]
So in this case, you are guaranteed that the order of initialization will be first the base class A, then the subobject B (since it appears first in the list of class members in the class definition), then the subobject C. The order of the initializer list is irrelevant, as is whether or not any of the members do or do not have a default constructor—if a member does not have a default constructor and it is not explicitly initialized in an initializer list, then it has an unspecified value.
but does that initialiser list determinethe ORDER of initialisation?
No. Initialization-list doesn't determine the the order of initialization of member data and the base subobject(s). Members are initialized in order of their declaration, and base subobjects are constructed in the order of their mention - from left to right:
struct A : B, C {} //B is constructed before C
Also, the base subobjects are constructed before the initialization of the member data.
struct A : B, C
{
D d;
E e;
};
Order of initialization in the above struct:
B => C => d => e
subobject subobject member member
And they're destructed in the reverse order.
Perhaps this example of broken code will help illustrate:
If I define a class like so:
class Connection {
boost::asio::tcp::ip::socket _socket;
boost::asio::io_service _io_service;
Connection() : _io_service(), _socket(_io_service)
{
}
};
This will fail in all modern compilers. Because _socket is defined first as a class member, the initialization list will try to initialize it first, despite the fact that the initialization list asks the compiler to initialize _io_service first. But since _io_service has not yet been initialized (the socket constructor depends on an initialized _io_service), the initialization of _socket will cause a segfault.
Perhaps somebody can quote the appropriate section of the standard that dictates this behaviour.
For the second half of the question, base classes will always be initialized before the classes own members.

Is the order of initialization guaranteed by the standard?

In the following code snippet d1's initializer is passed d2 which has not been constructed yet (correct?), so is the d.j in D's copy constructor an uninitialized memory access?
struct D
{
int j;
D(const D& d) { j = d.j; }
D(int i) { j = i; }
};
struct A
{
D d1, d2;
A() : d2(2), d1(d2) {}
};
Which section of C++ standard discusses order of initialization of data members?
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.
The C++ standard (ISO/IEC 14882:2003 12.6.2/5, Initializing bases and members) says:
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.
Bullet point 3 guarantees the order of nonstatic data member initialization.
In your example it will fail:
struct A
{
D d1, d2;
A() : d2(2), d1(d2) {}
};
d1: is initialised first as it is declared first.
d2: is then initialized.
As a result the initializer list will construct d1 using a reference to an invalid object (d2).
This is one reason to turn up your compilers warning level as high as possable.
And additionaly force it to report all warnings as errors.
This phenomenon is explained/highlighted in Item 13 of Meyer's Effective C++. It says that the destructor must destroy elements in the inverse order of its constructors, therefore all constructors must initialize elements in the same order, therefore they initialize them in the order in which they're declared (instead of the sequence of the initialization lists).
Yes. A good compiler should warn you that A::d2 will be initialized after A::d1.