order of object initialization and the use of constructor initializer

J

Jess

Hello,

When I define default constructors, I tend to use constructor
initializers for member data. However, I was told the order in which
members are initialized is determined by the order of declaration in
the class, instead of the order they appear in the constructor
initializer. This would introduce interdependencies. Therefore, it
is safer to avoid such interdependence by assigning values to these
members inside the constructor body rather than initializing them in
the intializer. Could someone explain to me why this is the case?
Moreover, what kind of error could possibly happen due to the
"interdependency"?

Many thanks!
 
G

Gianni Mariani

Jess said:
Hello,

When I define default constructors, I tend to use constructor
initializers for member data. However, I was told the order in which
members are initialized is determined by the order of declaration in
the class, instead of the order they appear in the constructor
initializer. This would introduce interdependencies. Therefore, it
is safer to avoid such interdependence by assigning values to these
members inside the constructor body rather than initializing them in
the intializer. Could someone explain to me why this is the case?
Moreover, what kind of error could possibly happen due to the
"interdependency"?

The order of construction is reversed for destruction. If you have
multiple constructors for the class, the order of construction is always
the same, as you said, no matter how the initializers are ordered.

Some compilers will issue a warning if the initializer list is not
consistent with the order of member declarations.

As for issues of interdependencies, I don't think I have ever come
across a situation where this was a problem.
 
R

Richard Herring

Jess said:
Hello,

When I define default constructors, I tend to use constructor
initializers for member data. However, I was told the order in which
members are initialized is determined by the order of declaration in
the class, instead of the order they appear in the constructor
initializer. This would introduce interdependencies. Therefore, it
is safer to avoid such interdependence by assigning values to these
members inside the constructor body rather than initializing them in
the intializer.

They *still* get initialised in the order of declaration, but using the
default constructor (provided it exists).

And you have no choice, if the members don't have a default constructor,
or their assignment operator is not defined, or it has a different
effect from the constructor.
 
J

Jess

If I have a class like:

class A{
int x;
int y;
string z;
B b;
A () : x(0), y(0) { x = 1;}
}

Then if I have a code that is "A a;" then I think the following
happens:
-- A() is called
-- x -> 0, y -> 0
-- z becomes null string
-- b is initialized by calling B's constructor
-- body of A() is entered, and x -> 1.

Is this right?
If A() is changed to:
A () : y(0), x(0) { x = 1;}

Then will the compiler complain? Thanks

Jess
 
V

Victor Bazarov

Jess said:
If I have a class like:

class A{
int x;
int y;
string z;
B b;
A () : x(0), y(0) { x = 1;}
}

Then if I have a code that is "A a;" then I think the following
happens:
-- A() is called
-- x -> 0, y -> 0
-- z becomes null string

... because that's how the default string c-tor behaves.
-- b is initialized by calling B's constructor

".. by calling B's _default_ constructor"
-- body of A() is entered, and x -> 1.

1 -> x
Is this right?

Pretty much.
If A() is changed to:
A () : y(0), x(0) { x = 1;}

Then will the compiler complain? Thanks

I don't know, you need to ask the compiler.

V
 
?

=?iso-8859-1?q?Kirit_S=E6lensminde?=

When I define default constructors, I tend to use constructor
initializers for member data. However, I was told the order in which
members are initialized is determined by the order of declaration in
the class, instead of the order they appear in the constructor
initializer. This would introduce interdependencies. Therefore, it
is safer to avoid such interdependence by assigning values to these
members inside the constructor body rather than initializing them in
the intializer. Could someone explain to me why this is the case?
Moreover, what kind of error could possibly happen due to the
"interdependency"?

There are cases where one attribute needs to be passed into a
superclass constructor or into another attribute's constructor and
these can cause problems.

Where you're passing between attributes then you should order them
correctly in the class definition. Where you have to pass into the
superclass I've done something like this (heavily abridged):

// Super's constructor needs an int pointer to use
class Super { Super( int * ); };

// We store the int here
class Holder { int m_attribute; };

// We can now get the int constructed before Super needs it
class Sub : Holder, Super { Sub(); };

// Pass the int to Super
Sub::Sub()
: Holder(), Super( &m_attribute ) {}

As I understand it the order of the super-classes in the definition of
Sub is important, not the order of the calls in the definition of
Sub's constructor. This is analogous to the case with the attribute
order in the class definition.


K
 
J

James Kanze

If I have a class like:
class A{
int x;
int y;
string z;
B b;
A () : x(0), y(0) { x = 1;}
}
Then if I have a code that is "A a;" then I think the following
happens:
-- A() is called
-- x -> 0, y -> 0
-- z becomes null string
-- b is initialized by calling B's constructor
-- body of A() is entered, and x -> 1.
Is this right?
If A() is changed to:
A () : y(0), x(0) { x = 1;}
Then will the compiler complain? Thanks

It might issue a warning, but the code is legal, and does
exactly what the previous code does.

The only time this is a problem is if you write something like:

A::A() : y( 0 ), x( y ) { x = 1; }

In this case, you actually have undefined behavior, because you
try to initialize x with y before having initialized y.
 
M

Marcus Kwok

Jess said:
When I define default constructors, I tend to use constructor
initializers for member data. However, I was told the order in which
members are initialized is determined by the order of declaration in
the class, instead of the order they appear in the constructor
initializer. This would introduce interdependencies. Therefore, it
is safer to avoid such interdependence by assigning values to these
members inside the constructor body rather than initializing them in
the intializer. Could someone explain to me why this is the case?
Moreover, what kind of error could possibly happen due to the
"interdependency"?

Here is a contrived example, but it demonstrates the point:


#include <iostream>

struct Foo {
const int c;
int i;

Foo(int x) : c(x), i(2 * c) { }
};


struct Bar {
int i;
const int c;

Bar(int x) : c(x), i(2 * c) { }
};


int main()
{
using std::cout;

Foo f(3);
cout << f.c << ", " << f.i << '\n';

Bar b(3);
cout << b.c << ", " << b.i << '\n';
}


Output:
3, 6
3, 8529120


In Foo, first the const int c is initialized with the value of 3, then
the int i is initialized with the value of (2*3).

In Bar, since i was declared before c, then i's initialization occurs
first. At this point the value of c is garbage (and thus reading it is
really undefined behavior), so i is initialized with 2*garbage before c
is initialized.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top