constructor initialization list

  • Thread starter Makis Papapanagiotou
  • Start date
M

Makis Papapanagiotou

Hello all,

There is a strange case where a class Test is composed from three objects of
other classes. i.e.

class Test
{ public:
Test();
private:
Point x;
Cat y;
Dog z;
};

where the classes Point, Cat, Dog are

class Point
{ public:
Point();
Point(Point& x, Dog& y);
private:
};

class Cat
{ public:
Cat();
Cat(Point& x, Dog& y);
private:
};

class Dog
{ public:
Dog();
Dog(Point& x, Cat& y);
private:
};

If we were calling the default constructors they is no problem, since as
STROUSTRUP is wrtiing in his book they are called in the order they are
defined in the class the main class (Test).

My big problem is why the following is working? i.e when the other
constructors are called.

Test::Test():x(), y(x,z), z(x,y)

since the creation of object "y" is related with the creation of object "z".

Can any body give an explanation of this strange behaviour?

Thanks in advance,
 
J

JKop

Can any body give an explanation of this strange behaviour?


The objects are contructed in the order in which they are, in the
Initialization List.

For objects that *aren't* listed in the initialization list, they are
constructed *before* all other member objects. So, given the following:


#include <string>

class Blah
{
public:
std::string a;
std::string b;
std::string c;
std::string d;
std::string e;
std::string f;

Blah() : c("Monkey!"), e(), a(), f("Ape!");
};


The order of in which the member objects are consructed in the above is as
follows:

b
d
c
e
a
f


-JKop
 
K

Karl Heinz Buchegger

Makis said:
Hello all,

There is a strange case where a class Test is composed from three objects of
other classes. i.e.

class Test
{ public:
Test();
private:
Point x;
Cat y;
Dog z;
};

where the classes Point, Cat, Dog are

class Point
{ public:
Point();
Point(Point& x, Dog& y);
private:
};

class Cat
{ public:
Cat();
Cat(Point& x, Dog& y);
private:
};

class Dog
{ public:
Dog();
Dog(Point& x, Cat& y);
private:
};

If we were calling the default constructors they is no problem, since as
STROUSTRUP is wrtiing in his book they are called in the order they are
defined in the class the main class (Test).

My big problem is why the following is working?

Define 'working'
i.e when the other
constructors are called.

It is still the same order:
x gets constructed first
y gets constructed next
z gets constructed last
Test::Test():x(), y(x,z), z(x,y)

The order in which constructors of member objects are called
is entirely defined by the order in which they are listed
in the class declaration. Here, in the initializer list
you simply specify *which* constructor to use for the members,
not the order in which they are called.
 
K

Karl Heinz Buchegger

JKop said:
The objects are contructed in the order in which they are, in the
Initialization List.

You might want to reread on this.
The order is defined entirely by the order the members are listed
in the class declaration. The initialzation list just selects which
constructor to use, but does not change the order in which members
get initialized.
 
M

Makis Papapanagiotou

Hello,

Sorry but this is not covering my question since in your example the objects
are not related to each other.

In my case they are

Test:: x( ), y(x,z), z(x,y)

So the object "y" in order to be constructed needs the object "z", but "z"
in order to be constructed needs "y" first.
Even though they are constructed.

Hence how this is done? Because it is done and it is not an error !!!


Thanks,
 
J

JKop

Karl Heinz Buchegger posted:
You might want to reread on this.
The order is defined entirely by the order the members are listed
in the class declaration. The initialzation list just selects which
constructor to use, but does not change the order in which members
get initialized.


I'm wrong!


I wasn't exactly sure so I went off and tested it, but then I realized
that my "test" would have produced the same results either way.

So... in summation:

Objects are constructed in the order in which they appear in the class
declaration.

(I think what had me confused is where you have multiple base classes
and you use the initialization list to specify the order in which the
base classes' constructors are called.)


-JKop
 
K

Karl Heinz Buchegger

Makis said:
Hello,

Sorry but this is not covering my question since in your example the objects
are not related to each other.

In my case they are

Test:: x( ), y(x,z), z(x,y)

So the object "y" in order to be constructed needs the object "z", but "z"
in order to be constructed needs "y" first.
Even though they are constructed.

Hence how this is done? Because it is done and it is not an error !!

It all depends on what the Cat or Dog constructor do with
the passed reference.

When the Cat constructor is called and passed the Dog object,
the Dog object isn't yet fully constructed, but the memory for
that object has already been reserved. So for the Cat object it
is safe to eg. store a pointer to the Dog object or create a reference
to it. You, the programmer, know that at exactly this memory location
eventually there will be a fully constructed Dog object, when the
whole initialization is completed.
 
M

Makis Papapanagiotou

Hello,

Yes it is still in the same order:

x gets constructed first
y gets constructed next
z gets constructed last

At least thats what we see if we put a "cout" stetement in the
constructors...

Thanks,
 
K

Karl Heinz Buchegger

Makis said:
Hello,

Yes it is still in the same order:

x gets constructed first
y gets constructed next
z gets constructed last

At least thats what we see if we put a "cout" stetement in the
constructors...

Well. I got your question wrong, mostly because you didn't ask
a specific question other then: "Why is this <lots of code> not wrong?"
Moral of story: If you want to emphasize on something, code is a good
thing, but tell us exactly what is puzzeling you.

See my other reply for some explanations.
 
J

Jeff Flinn

JKop said:
Karl Heinz Buchegger posted:



I'm wrong!


I wasn't exactly sure so I went off and tested it, but then I realized
that my "test" would have produced the same results either way.

So... in summation:

Objects are constructed in the order in which they appear in the class
declaration.

(I think what had me confused is where you have multiple base classes
and you use the initialization list to specify the order in which the
base classes' constructors are called.)

Wrong again.

Jeff F
 
G

Gianni Mariani

JKop said:
The objects are contructed in the order in which they are, in the
Initialization List.


I don't think that's right. The order of member construction is the
order in which they are defined in the class. The order of member
destruction is the reverse order in which they are defined in the class,
regardless of the order of the initializer list. Inherited classes are
constructed before members in the order in which they are inherited and
destructed in reverse order of construction.

#include <iostream>

template <int num>
class Yell
{
public:
int m_num;

Yell()
: m_num()
{
std::cout << num << " Default" << std::endl;
}

Yell( int i )
: m_num( i )
{
std::cout << num << " Nondefault( " << i << " )" << std::endl;
}

~Yell()
{
std::cout << num << " DESTRUCT( " << m_num << " )" << std::endl;
}

};

class Blah
: public Yell<10>, public Yell<11>
{
public:
Yell<1> a;
Yell<2> b;
Yell<3> c;
Yell<4> d;
Yell<5> e;
Yell<6> f;

Blah() : c(100), e(), a(), f(200), Yell<11>( 300 )
{
}
};

int main()
{
Blah x;
}

output:

10 Default
11 Nondefault( 300 )
1 Default
2 Default
3 Nondefault( 100 )
4 Default
5 Default
6 Nondefault( 200 )
6 DESTRUCT( 200 )
5 DESTRUCT( 0 )
4 DESTRUCT( 0 )
3 DESTRUCT( 100 )
2 DESTRUCT( 0 )
1 DESTRUCT( 0 )
11 DESTRUCT( 300 )
10 DESTRUCT( 0 )
 
R

Ron Natalie

JKop said:
The objects are contructed in the order in which they are, in the
Initialization List.

For objects that *aren't* listed in the initialization list, they are
constructed *before* all other member objects. So, given the following:

It doesn't matter whether they are listed or NOT.
The initilization list has NO BEARING on the order of connstruction.
 
C

Chris Theis

JKop said:
Karl Heinz Buchegger posted:



I'm wrong!


I wasn't exactly sure so I went off and tested it, but then I realized
that my "test" would have produced the same results either way.

So... in summation:

Objects are constructed in the order in which they appear in the class
declaration.

(I think what had me confused is where you have multiple base classes
and you use the initialization list to specify the order in which the
base classes' constructors are called.)

Sorry to tell you, but you´re wrong again. The initialization list does not
specify the order of execution of the base class ctors. To make a long
matter short - read the FAQ, item 25.14.

Chris
 
D

DaKoadMunky

The objects are contructed in the order in which they are, in the
Initialization List.

For objects that *aren't* listed in the initialization list, they are
constructed *before* all other member objects.

This is absolutely false.

Why would you think this?

How can you expect people to take your claim of being an expert level C++
programmer seriously when you can get something like this so wrong?
 
J

JKop

DaKoadMunky posted:
This is absolutely false.

Why would you think this?

How can you expect people to take your claim of being an expert level C++
programmer seriously when you can get something like this so wrong?


I consider it to be one of those aspects which I wouldn't really pay much
attention to, until a scenrio comes up where I need to, at which point I'll
consult a reference.

For example, I know how "const" works with pointers, ie.:

const char* p_blah;

The variable "p_blah" is *not* const, but what it points to *is*.


char* const p_blah;

The variable "p_blah" is const, but what it points to is *not*.


So anyway, I've got that well and trully asimiliated.

But then when it comes to pointers to pointers, I'm not sure how the whole
const system works there. I haven't needed to use it thus far, so I haven't
read up on it. When and if the time comes that I need to use it, I will
*not* guess (similarly with the constructor order scenario), I will consult
a reference.

If I were to learn everything about everything all at once, then it would
take me a very long time to get proficient, sort of like how when learning
to drive, you don't spend a few hours messing with the clutch, then spend a
few hours driving. Instead you go out and do them both together and
eventually they'll come together.


So in summation, while I was wrong, still if there were a scenario in which
constructor order was important, I would've definitely consulted a
reference.

I say "consult a reference"; which I would like to mean the C++ Standard...
but for Christ's sake the thing is just too God damn long!


So anyway, yes I was wrong; but in my defense, if it were really that
important, I would've sought clarity.


-JKop
 
D

DaKoadMunky

I consider it to be one of those aspects which I wouldn't really pay much
attention to, until a scenrio comes up where I need to, at which point I'll
consult a reference.
When and if the time comes that I need to use it, I will
*not* guess (similarly with the constructor order scenario), I will consult
a reference.

So you are saying that you did not use any reference materials to learn how the
order of items in a base/member initializer list impacted execution order of
those initializers?

That is okay. We can't know everything. I have been using C++ for almost a
decade and I can tell you almost nothing about I/O using streams. I just have
not needed them. I really don't know what the keyword volatile is for either.

The things I do know I have learned either out of curiousity because I thought
they might be important or because I was fortunate enough to have been exposed
to those things via study of books and magazines.

I would like to know though why you think you had the knowledge required to
make a definitive statement regarding how the order of items in a base/member
initializer list impacted execution order of those initializers.

Did somebody teach you? Okay then. That happens. Sadly I have seen C++ books
on the store shelves that contained erroneous information. Some of the C++
"tips" at www.devx.com are simply horrendous. One of them I just read led to
undefined behavior and even if it didn't lead to undefined behavior it had no
value, but there it was posted as a "tip."

Did you base your statements on observed behavior? For shame. Just because a
compiler accepts a statement and then executes it in a certain way does not
mean it is correct. The only authority is the Standard (which I keep meaning
to get...honest...I am poor...please send me $65 for the hardback version...I
hate reading on the monitor)

Were your statements based on how you think the initializer list should work?

Just curious.
 
J

JKop

DaKoadMunky posted:
So you are saying that you did not use any reference materials to learn
how the order of items in a base/member initializer list impacted
execution order of those initializers?

Correct.


That is okay. We can't know everything. I have been using C++ for
almost a decade and I can tell you almost nothing about I/O using
streams. I just have not needed them. I really don't know what the
keyword volatile is for either.

The things I do know I have learned either out of curiousity because I
thought they might be important or because I was fortunate enough to
have been exposed to those things via study of books and magazines.

I would like to know though why you think you had the knowledge
required to make a definitive statement regarding how the order of
items in a base/member initializer list impacted execution order of
those initializers.


I tested it.

For instance - if some-one said to me, "will this compile?", and I wasn't
sure, then I wouldn't read the Standard, I'd try compile it.

So I made up a little test program to see what order in which the
contructors were invoked. The results suggested what I posted. But... then a
couple of minutes later, I realized that either way the test would've given
the same results.


So I unintentionally posted misinformation.


Now I know!

Did somebody teach you?

Books.


Okay then. That happens. Sadly I have seen
C++ books on the store shelves that contained erroneous information.


void main() {}

Some of the C++ "tips" at www.devx.com are simply horrendous. One of
them I just read led to undefined behavior and even if it didn't lead
to undefined behavior it had no value, but there it was posted as a
"tip."

Did you base your statements on observed behavior? For shame. Just
because a compiler accepts a statement and then executes it in a
certain way does not mean it is correct. The only authority is the
Standard (which I keep meaning to get...honest...I am poor...please
send me $65 for the hardback version...I hate reading on the monitor)


Yes, correct, the only authority is the Standard! One day I thought to
myself, hmm... I'll just print it out and read it all. It might take a
while, but hey!

So I emailed it to some-one who worked in an office with a printer and he
printed it out for me.

The next day I was handed a doorstep.

So, while I'd very much like to read through the entire C++ Standard and
attain absolute clarity, life is too short! Such a vast amount of
information is just a bit overwhelming to me.

Were your statements based on how you think the initializer list should
work?


Partly I suppose. I probably didn't scrutanize my test results so closely
because they were showing me what I wanted to see. (Sort of like how when I
think I've lost something really important, I check all my other pockets
before I check the one I thought I had it in. Sure it would've been logical
to check the most likely location first, but in anxiety I compusively delay
my misery).


-JKop
 

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

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,013
Latest member
KatriceSwa

Latest Threads

Top