Changing initialization order in constructor - c++

class a
{
public:
a() : b(5), a1(10) //will firstly initialize a1 then b, so order here doesn't matter
int a1;
private:
int b;
}
The question is how to change the order (to have b initialized before a1)? I must have public members above private so that solution isn't okay for me. Of course here I use ints, the problem is more complex but it's just an example which shows what is my problem.

You cannot change the order of initialization, that is always defined by the order of declaration of the members in your class. This is necessary because the order of destruction must be the inverse of the order of construction, and if you changed the order of construction, the compiler would be forced to keep track of which order you have initialized your members in in order to generate proper destruction sequences.
So my advice is:
Just live with it, and;
Do not depend on the order of construction of your member variables.
To achieve point 2), you can provide default constructors for your members to do default initialization, and then initialize your members properly in the order you want inside the body of your constructor (in other words, decouple construction from logical initialization).

The order of initialization is determined by the order of declaration of the member variables. So if you want b to be initialized before a, you have to declare it before.
class a
{
public:
a() : b(5), a1(10) {}
private:
int b;
public:
int a1;
};

If I understand you correct you have some kind of style guide saying that public members should be before private.
In that case I would suggest you declare all your member variables private and create accessor functions to them instead. That way you get around it.
class a
{
public:
a() : _a1(5), _b(10)
int a1() const { return _a1; }
void a1(int value) { _a1 = value; }
int b() const { return _b; }
void b(int value) { _b = value; }
private:
int _a1;
int _b;
}
any sane compiler will anyway optimize it so the overhead will be minimal.

Make your b object private, declared it before a1, and make an accessor function for accessing the content of b. [If necessary, make it return a reference to the b object, so the calling code can modify it - although that is quite clearly bad design to expose the internals of a class to the calling code, whether it's through a public declaration or through returning a reference]

Related

C++ multiple access specifiers and order of initialization

We know that in the following code
class Foo1 {
private:
int i;
bool b;
public:
Foo1() : i(7), b(false) {}
};
"i" is going to be init before "b". If I try to init "b" before "i", I'll get a warning.
what about this case:
class Foo2 {
private:
int i;
private:
bool b;
public:
// what happens if b is first because compiler reordered?
Foo2() : b(false), i(7) {}
};
?
We know that the compiler is free to order "i" and "b" since they are in separate access specifiers.
So what is the order of initialization in this case?
anything guaranteed like in the previous simple case?
The order of initialization is guaranteed; i is always initialized before b. Non-static data members are initialized in the order of their declaration in the class definition, regardless of their access specifiers.
[class.base.init]/13.3
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 did the creator of C++ decide to use constructor initializer list to initialize base classes?

Why did the creator of C++ decide to use constructor initializer list to initialize base classes? Why didn't he instead choose to use syntax like the second comment line in the following code?
class A{
public:
A() { }
};
class B : A{
public:
B() : A() { } // Why decide to use this one, using constructor initializer, to initialize base class?
B() { A(); } // Why not choose this one? It's easy for me to understand if it was possible.
};
int main(int argc, char *argv[]){
/* do nothing */
}
The advantage of using an initializer list is, that you have a completely initialized object in the body of the constructor.
class A {
public:
A(const int val) : val(val) { }
private:
const int val;
};
class B : A{
public:
B() : A(123) {
// here A and B are already initialized
}
};
So you have a guarantee that all members, even those of the parent, are not in an undefined state.
Edit
In the example of the question it is not necessary to call the base class in the initializer list, this is done automatically. So I slightly modified the example.
I can see a few possible alternatives to the current C++ rule that base classes and data members of a class type are initialised in the mem-initialiser list of the class type's constructor(s). They all come with their set of issues, which I will discuss below.
But first, note that you cannot simply write a derived constructor like this:
struct Derived : Base
{
Derived()
{
Base(42);
}
};
and expect the line Base(42); to call the base class constructor. Everywhere else in C++, such a statement creates a temporary object of type Base initialised with 42. Changing its meaning inside a constructor (or just inside its first line?) would be a syntax nightmare.
Which means that new syntax would need to be introduced for this. In the rest of this answer, I will use a hypothetical construct __super<Base> for this.
Now on to discuss possible approaches which would be closer to your desired syntax, and present their problems.
Variant A
Base classes are initialised in the constructor body, while data members are still initialised in the mem-initialiser list. (This follows the letter of your question the closest).
The would have the immediate problem of stuff executing in different order than it's written. For very good reasons, the rule in C++ is that base class subobjects are initialised before any data members of the derived class. Imagine this use case:
struct Base
{
int m;
Base(int a) : m(a) {}
};
struct Derived
{
int x;
Derived() :
x(42)
{
__super<Base>(x);
}
};
Written like this, you could easily assume x would be initialised first and then Base would be initialised with 42. However, that would not be the case and instead reading x would be undefined.
Variant B
Mem-initialiser lists are removed altogether, base classes are initialised using __super, and data members are simply assigned in the constructor body (pretty much the way Java does it).
This cannot work in C++ because initialisation and assignment are fundamentally different concepts. There are types where the two operations do vastly different things (e.g. references), and types which are not assignable at all (e.g. std::mutex).
How would this approach deal with a situtation like this?
struct Base
{
int m;
Base(int a) : { m = a; }
};
struct Derived : Base
{
double &r;
Derived(int x, double *pd)
{
__super<Base>(x); // This one's OK
r = *pd; // PROBLEM
}
};
Consider the line marked // PROBLEM. Either it means what it normally does in C++ (in which case it assigns a double into a "random place" which the uninitialised reference r references), or we change its semantics in constructors (or just in initial parts of a constructor?) to do initialisation instead of assignment. The former gives us a buggy program while the latter introduces totally chaotic syntax and unreadable code.
Variant C
Like B above, but introduce special syntax for initialising a data member in the constructor body (like we did with __super). Something like __init_mem:
struct Base
{
int m;
Base(int a) : { __init_mem(m, a); }
};
struct Derived : Base
{
double &r;
Derived(int x, double *pd)
{
__super<Base>(x);
__init_mem(r, *pd);
}
};
Now, the question is, what have we achieved? Previously, we had the mem-initialiser list, a special syntax to initialise bases and members. It had the advantage that it made clear these things happen first, before the constructor body starts. Now, we have a special syntax to initialise bases and members, and we need to force the programmer to put it at the start of the constructor.
Note that Java can get away with not having a mem-initialiser list for several reasons which don't apply to C++:
The syntax for creating an object is always new Type(args) in Java, whereas Type(args) can be used in C++ to construct objects by value.
Java only uses pointers, where initialisation and assignment are equivalent. For many C++ types, there operations are distinct.
Java classes can only have one base class, so using just super is enough. C++ would need to differentiate which base class you're referring to.
B() : A() { }
This will initialize the base class in user defined way.
B() { A(); }
This will NOT initialize the base class in user defined way.
This will create an object inside of constructor i.e B(){}
I think first initialization has better readability compared to the second and you can also deduce class hierarchy.

Best way to initialize class members?

Using the c++11 standard, I can initialize class members in two ways:
class MyClass
{
private:
int a = 5;
};
or
class MyClass
{
private:
int a;
public:
MyClass()
{
a = 5;
}
};
Is either method superior to the other for any reason, or is it more an individual style choice?
The second example is not initialisation.
So, of the two examples, the first is the best way to initialise class members.
The traditional way to initialise looks like this:
class MyClass
{
private:
int a;
public:
MyClass()
: a(5)
{}
};
Though we now have inline initialisers as in your first example, since C++11.
This page from the Standard C++ Foundation suggests that, all else being equal, you should prefer to use an initializer list. That is:
Prefer
class Foo {
public:
Foo(int bar) : m_bar(bar) { }
private:
int m_bar;
};
over
class Foo {
public:
Foo(int bar) {
m_bar = bar;
}
private:
int m_bar;
};
Their rationale:
Consider the following constructor that initializes member object x_
using an initialization list: Fred::Fred() : x_(whatever) { }. The
most common benefit of doing this is improved performance. For
example, if the expression whatever is the same type as member
variable x_, the result of the whatever expression is constructed
directly inside x_ — the compiler does not make a separate copy of the
object. Even if the types are not the same, the compiler is usually
able to do a better job with initialization lists than with
assignments.
The other (inefficient) way to build constructors is via assignment,
such as: Fred::Fred() { x_ = whatever; }. In this case the expression
whatever causes a separate, temporary object to be created, and this
temporary object is passed into the x_ object’s assignment operator.
Then that temporary object is destructed at the ;. That’s inefficient.
As if that wasn’t bad enough, there’s another source of inefficiency
when using assignment in a constructor: the member object will get
fully constructed by its default constructor, and this might, for
example, allocate some default amount of memory or open some default
file. All this work could be for naught if the whatever expression
and/or assignment operator causes the object to close that file and/or
release that memory (e.g., if the default constructor didn’t allocate
a large enough pool of memory or if it opened the wrong file).
Conclusion: All other things being equal, your code will run faster if
you use initialization lists rather than assignment.
Regarding default initialization (such as Foo(): m_bar(5) { }) I would also go with the initializer list approach (or the C++11 member initialization approach) just for consistency with the above guideline.

C++ constructor initialization reference assignment

I am sure this question has been asked before. But I cannot seem to find the exact answer that I am looking for. Basically I am trying to create an object of the class as a member of the other class and pass one of the members by reference to the owned object through the constructor. Sometimes this seems to work, other times I get a random value.
I think that I am not understanding some rudimentary rule of initialization order
Here is the code example:
class Foo
{
public:
Foo();
private:
int b;
Bar c;
};
class Bar
{
public:
Bar(int& parm);
private:
int& b_ref;
};
Foo::Foo(): b(0), c(b)
{}
Bar::Bar(int& parm): b_ref(parm)
{}
What I want is for c to own a reference to b and be able see the value as it changes.
Should I not use the initialization list in this case?
The rule is that objects are initialised in the order of their declaration in the class. In this case, it means that b is initialised before c, so this code should always work correctly.
If you swapped the order of the b and c members, then the int referenced by param would not yet be initialised in the constructor of Bar.

Why are member variables visible in c++ constructor initialization lists?

I came across this due to a bug in my code and I'm curious why it's allowed. What reason is there that allows object members to be visible in the constructor initialization list?
#include <stdio.h>
class derived {
private:
int * value2;
public:
derived();
};
derived::derived()
: value2(value2){} // Uninitialized self-assignment
int main()
{
derived thisChild;
}
Clang gives a warning about this but unfortunately g++ does not.
So you can initalise one member using another; this is perfectly fine if the other has already been initialised, or if you're just using its address to initialise a pointer or reference. For example:
struct Thingy
{
int & r;
int a;
int b;
Thingy(int x) :
r(a), // OK - a has a valid address, and we're not using the value
a(x),
b(a) // OK - a has been initialised
{}
};
It would be rather tricky to allow that and disallow your example.
If it is not visible, you cannot write this:
A(int n) : some_num(n), another_num(some_num*10) {}
then what would be the point of member-initialization list?
As for self-initialization (uninitialized variable), you can do even this:
int xyz = xyz; //will compile
You can think of the initialization list as part of the body of the method (specifically the constructor), so it is natural that you can access the member variables of an object in one of its methods
Also, you might want to reuse an already created member variable to initialize others -- note: you will have to know the exact order of initialization (order of member variable declaration) to make sure you are using this portably
I think you mean why are member variables accessible in initializer expressions.
One reason is that the initialization of one member variable can depend on another.
That's fragile, but sometimes necessary to avoid awkward code such as artificial base classes.