Use member in constructor initializer list [duplicate] - c++

This question already has answers here:
Constructor initialization-list evaluation order
(3 answers)
Closed last year.
Can I safely use members to initialize others?
class Class {
public:
Class(X argument) : memberA(argument), memberB(memberA) {}
A memberA;
B memberB;
};
Here we use the argument to the constructor to initialize memberA. We then rely on the fact that this happens before the initialization of memberB and initialize memberB using memberA.
If we assume X, A, and B to be std::string the above example works (tested with gcc), as long as we do not change the order in which the members are declared. But is this actually guaranteed by the standard or am I abusing an implementation detail of the compiler?

Yes, this is safe as per class.base.init#15
The expression-list or braced-init-list of a mem-initializer is in the function parameter scope of the constructor and can use this to refer to the object being initialized.
This Note also has an example with this->i to show that previously initialized class members can be used to initialize other class members inside a mem-initializer. (The this-> is only necessary in this example to disambiguate the member and the constructor parameter, both named i).
Be careful that the member is already initialized before using it, since from class.base.init#13.3
... 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).

Related

In which order object class members with no parameters in their constructor functions are initialized? [duplicate]

This question already has answers here:
Initialization Order of Class Data Members
(2 answers)
Closed 4 years ago.
I have three class. First one is the 'Game', which is dependent to the other two. My second class is 'Window', which is a dependence for the third class 'VKBase'. Those last two classes have no parameters in their constructor functions. Game contains the others as object members, and Window have to get initialised before VKBase.
class Game
{
Boolean bit = true;
Window window;
VKBase VkBase;
public:
Game();
~Game();
void _Set();
void Loop();
void Exit();
};
Because that these two class not have parameters in their constructor functions, i can't initialise them in the constructor function of the Game. So they will get initialised whenever i create an object from the class Game.
But the question is, since initialisation order is important, which one will get initialised first? The window or the VkBase?
Initialization order is always left-to-right: first class bases, left-to-right, then member variables in declaration order. So the first one to be initialized in your class is bit, and then follows window.
In which order object class members [...] are initialized?
In the order in which they were declared. In your example, bit is initialized first, window second, VkBase third. Whether these data members have a default constructor or one depending on parameters doesn't matter here.
Because that these two class not have parameters in their constructor functions, i can't initialise them in the constructor function of the Game
You kind got that wrong, you do in fact initialize the instances by calling the default constructor. Note that for any class that has a default constructor,
ClassWithDefaultCtor instance;
does call this default constructor when this variable is instantiated (might be when an enclosing class is constructed, if the above declaration is a class data member). This syntax is called default initialization, and this is exactly what happens in your class. Note that you can change the above to
ClassWithDefaultCtor instance{};
which might make it clearer that the object is properly initialized.

Why do non-constant static variables need to be initialized outside the class? [duplicate]

This question already has answers here:
C++ static member variable and its initialization
(5 answers)
How to initialize private static members in C++?
(18 answers)
Closed 5 years ago.
I know that non-constant static variables need to be initialized outside the class definition but, is there a reason for this?
class A {
static int x = 0 // compile error;
static int y;
};
int A::y = 0; // fine
Essentially it's because x exists independently of the number of instances of A that are created.
So storage for x needs to be defined somewhere - you can't rely on an instance of A to do that, and that's what
A::x = 0;
in exactly one translation unit, does.
When the const qualifier is present, the static variable can be considered as a constant expression. Initializing it in the class definition goes to that effect. It's just some constant value, may not even need any storage.
But in the other case, it's not a constant expression. It definitely needs storage. And as #Bathsheba points out, it needs to be defined in only one translation unit (pre-C++17). Generally speaking, a declaration that contains an initializer is also a definition. So it just can't be initialized when declared.
Starting with C++17, that variable can be an inline variable. So the definition can in fact be included with the class declaration
class A {
static inline int x = 0;
};
And the compiler will sort out all those declarations to mean the same storage.
after a small research, found this (from bogotobogo) :
we cannot initialize a static member variable inside the class declaration. That's because the declaration is a description of how memory is to be allocated, but it doesn't allocate memory. We allocate and initialize memory by creating an object using that format.
In the case of a static class member, we initialize the static member independently, with a separate statement outside the class declaration. That's because the static class member is stored separately rather than as part of an object.
The exception to the initialization of a static data member inside the class declaration is if the static data member is a const of integral or enumeration type.
my take from this is ..
static members exist as members of the class rather than as an instance in each object of the class.
when you initialize the static variable inside the class declaration, as a concept it will be re-initialized (not the actual behaviour) on every creation of an object/instance of the class,
[since the class declaration is the blueprint of which every new object of the class is construct].
but we know that this is not supposed to be the behavior of a static member, so the initialization of this member is outside of the class declaration.
I found this explanation a more intuitive one, but still the formal explanation remains the first one.
Apart from what others have said, there is currently no place (pre C++ 11) within a class where you could initialize a static member (because members (both static and non-static can't be initialized where declared). For non-static members, we use either the constructor or the member initializer list to do the initialization. But this means we have to create an instance of the class.
Since a static member initialization can't depend on an instance being created, it's done outside the class where the member is declared.

Initialization of Members in constructor [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
C++ initialization lists
class Base
{
public:
int m_nValue;
Base(int nValue=0)
: m_nValue(nValue)
{
}
};
In this code, is the constructor initializing m_nvalue member variable?
I am not sure of this syntax:
Base(int nValue=0) : m_nValue(nValue) {}
We normally write it as:
Base(int nValue) { m_nValue = nValue;}
Can some one explain the above syntax of C++?
This syntax:
Base(int nValue=0)
: m_nValue(nValue)
is called the member initializer. It will initialize m_nValue with given nValue. This syntax is usually preferred in C++ since it is executed before the body of the constructor.
It's called member initializer list.
The member initializer list consists of a comma-separated list of initializers preceded by a colon. It’s placed after the closing
parenthesis of the argument list and before the opening bracket of the function body
Conceptually, these initializations
take place when the object is created and before any code within the brackets is executed.
Note:
You can’t use the member initializer list syntax with class methods other than constructors.
The way of initializing a variable in your code is called as member initializer list.
Generally we use such list to initialize const member variable (normal - non const also) we because at the time of construction we can give some value to const variable.
Second type of Initialization is basically a normal Parametrised constructor. That is used when you are having a object and at the time of creation of object you want to initialize the member variable.

Is the order of construction of member variables of a class undefined in c++? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Member fields, order of construction
If i have a class with two members like this:
class A
{
int a;
int b;
A() {}
};
Is the order in which a and b are constructed undefined?
If I use cl, then no matter in which order I call the constructors, the members are always constructed in the order in which they are declared in the class. In this case it would always be a then b, even if I define the constructor for A like:
A() : b(), a() {}
But I am assuming that that is just the behaviour of the specific compiler.
No. Members are constructed in the order in which they are declared.
You are advised to arrange your initializer list in the same order, but you are not required to do so. It's just very confusing if you don't and may lead to hard-to-detect errors.
Example:
struct Foo {
int a; int b;
Foo() : b(4), a(b) { } // does not do what you think!
};
This construction is actually undefined behaviour, because you're reading an uninitialized variable in the initializer a(b).
Standard reference (C++11, 12.6.2/10):
— 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).
The order of initialization is the same as the order of declaration in the class.
If the order on the constructor's initialization list is different then compilers usually issue a warning. For example for the class:
class A {
public:
A() : b(1), a(b) {}
private
int a;
int b;
};
GCC will warn that:
$ g++ -Wall c.cc
c.cc:5: error: expected `:' before ‘int’
c.cc: In constructor ‘A::A()’:
c.cc:6: warning: ‘A::b’ will be initialized after
c.cc:5: warning: ‘int A::a’
c.cc:3: warning: when initialized here
This is because it can easily lead to errors. In the above example value of a will be unspecified.

Memberwise Initialization [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
C++ initialization lists
What is the difference between member-wise initialization and direct initialization in a class?
What is the difference between the two constructors defined in the class?
class A
{
public:
int x;
int y;
A(int a, int b) : x(a), y(b)
{}
A(int a, int b)
{
x = a;
y = b;
}
};
The theoretical answers have been given by other members.
Pragmatically, member-wise initialization is used in these cases :
You have a reference attribute (MyClass & mMyClass) in your class. You need to do a member-wise initialization, otherwise, it doesn't compile.
You have a constant attribute in you class (const MyClass mMyClass). You also need to do a member-wise initialization, otherwise, it doesn't compile.
You have an attribute with no default constructor in your class (MyClass mMyClass with no constructor MyClass::MyClass()). You also need to do a member-wise initialization, otherwise, it doesn't compile.
You have a monstruously large attribute object (MyClass mMyClass and sizeof(MyClass) = 1000000000). With member-wise initialization, you build it only once. With direct initialization in the constructor, it is built twice.
First one uses initialization and second one does NOT use initialization, it uses assignment. In the second one, the members x and y are default-initialized first (with zero), and then they're assigned with a and b respectively.
Also note that in the second one, members are default initialized only if the types of members are having non-trivial default constructor. Otherwise, there is no initialization (as #James noted in the comment).
Now see this topic to know:
What is a non-trivial constructor in C++?