473,385 Members | 1,506 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,385 software developers and data experts.

How is member initialisation ordered?

Here is a program that doesn't work as intended:

#include <iostream>
using namespace std;

class MyClass
{
int bar;
int foo;
public:
MyClass(int foo_, int bar_) : foo(foo_), bar(bar_ + foo) { }
void print() const { cout << foo << " " << bar << endl; }
};

int main()
{
MyClass obj(3,6);
obj.print(); // intended to show "3 9" but doesn't
return 0;
}

When I reverse the order in which members foo and bar are declared, the
program works properly. It appears as though members are initialised in the
order in which they are declared. Is this gaurenteed? Thanks.
Jul 22 '05 #1
6 1389
Jason Heyes wrote:
It appears as though members are initialised in the order in which they
are declared. Is this gaurenteed?


Yes, it is. See section 12.6.2/5 of the C++ standard.

--
Russell Hanneken
rg********@pobox.com
Remove the 'g' from my address to send me mail.

Jul 22 '05 #2
"Jason Heyes" <ge******@optusnet.com.au> wrote in message
news:3f***********************@news.optusnet.com.a u...
Here is a program that doesn't work as intended:

#include <iostream>
using namespace std;

class MyClass
{
int bar;
int foo;
public:
MyClass(int foo_, int bar_) : foo(foo_), bar(bar_ + foo) { }
void print() const { cout << foo << " " << bar << endl; }
};

int main()
{
MyClass obj(3,6);
obj.print(); // intended to show "3 9" but doesn't
return 0;
}

When I reverse the order in which members foo and bar are declared, the
program works properly. It appears as though members are initialised in the order in which they are declared. Is this gaurenteed? Thanks.


The rule of thumb: The compiler tries to ensure everything destructs in
order reversed from their construction. (You should match this rule among
allocations and de-allocations.)

Hence, everything constructs in a known, defined order. Inside one class,
this order is top-to-bottom for each members.

That's why lint programs will complain when members appear to construct out
of order.

Even if you obey that rule, and construct bar before foo, don't abuse your
knowledge of the mechanics to indulge in prank construction arguments.
Reading a member inside another member's constructor should be well outside
everyone's "sane subset".

Further, the code above causes undefined behavior. 'bar(bar_ + foo)' reads
the member 'foo' before it has constructed. In practice this only means
'foo' returns garbage, but in theory "undefined behavior" means anything
could happen. For example, if 'foo' somehow occupied memory not yet switched
by hardware to permit reads, the program would crash.

--
Phlip
Jul 22 '05 #3
On Wed, 3 Dec 2003 17:13:23 +1100, "Jason Heyes"
<ge******@optusnet.com.au> wrote:
Here is a program that doesn't work as intended:

#include <iostream>
using namespace std;

class MyClass
{
int bar;
int foo;
public:
MyClass(int foo_, int bar_) : foo(foo_), bar(bar_ + foo) { }
void print() const { cout << foo << " " << bar << endl; }
};

int main()
{
MyClass obj(3,6);
obj.print(); // intended to show "3 9" but doesn't
return 0;
}

When I reverse the order in which members foo and bar are declared, the
program works properly. It appears as though members are initialised in the
order in which they are declared. Is this gaurenteed? Thanks.


Yup, order of member declaration in the class, not in the
constructor's initializer list. I think you can violate it by moving
the initializations into the body of the constructor, not that it
would be a good idea.
Jul 22 '05 #4

"Dan W." <da**@raytron-controls.com> schrieb im Newsbeitrag
news:4i********************************@4ax.com...
On Wed, 3 Dec 2003 17:13:23 +1100, "Jason Heyes"
<ge******@optusnet.com.au> wrote:
Here is a program that doesn't work as intended:

#include <iostream>
using namespace std;

class MyClass
{
int bar;
int foo;
public:
MyClass(int foo_, int bar_) : foo(foo_), bar(bar_ + foo) { }
void print() const { cout << foo << " " << bar << endl; }
};

int main()
{
MyClass obj(3,6);
obj.print(); // intended to show "3 9" but doesn't
return 0;
}

When I reverse the order in which members foo and bar are declared, the
program works properly. It appears as though members are initialised in theorder in which they are declared. Is this gaurenteed? Thanks.


Yup, order of member declaration in the class, not in the
constructor's initializer list. I think you can violate it by moving
the initializations into the body of the constructor, not that it
would be a good idea.


No, that would be assignements. The initialization would still happen in the
order
of the declaration. But I think it would be a good idea, at least in the
case of ints
to assign them in the body rather than relying on the order of the members
in the
header file. But even better would be:
class MyClass {
....
MyClass(int foo_, int bar_) : foo(foo_), bar(bar_ + foo_) { } // note
the underscore in foo_

CU
Norbert
Jul 22 '05 #5
"Norbert Riedlin" <nr@netatec.de> wrote in message
news:bq*************@ID-212925.news.uni-berlin.de...

No, that would be assignements. The initialization would still happen in the order
of the declaration. But I think it would be a good idea, at least in the
case of ints
to assign them in the body rather than relying on the order of the members
in the
header file. But even better would be:
class MyClass {
...
MyClass(int foo_, int bar_) : foo(foo_), bar(bar_ + foo_) { } // note
the underscore in foo_

CU
Norbert


Yes that is better. What happens when members have non-trivial
initialisation? Here is an example:

class MyClass
{
Bar bar; // Bar has constructor with a Foo object parameter
Foo foo;

Foo make_foo(std::string name); // involves some serious work

public:
MyClass(std::string name) : foo(make_foo(name)), bar(foo) { }
};

I could write

MyClass(std::string name) : foo(make_foo(name)), bar(make_foo(name)) { }

but that involves calling make_foo twice. I think I'd better declare the
members in the right order instead.
Jul 22 '05 #6
>
Yes that is better. What happens when members have non-trivial
initialisation? Here is an example:

class MyClass
{
Bar bar; // Bar has constructor with a Foo object parameter
Foo foo;

Foo make_foo(std::string name); // involves some serious work

public:
MyClass(std::string name) : foo(make_foo(name)), bar(foo) { }
};

I could write

MyClass(std::string name) : foo(make_foo(name)), bar(make_foo(name)) { }
but that involves calling make_foo twice. I think I'd better declare the
members in the right order instead.


You are right. Always declare the members in the right order, but don't
depend on it.
You might be faced with classes written by other developers or with your
classes
changed by other developers. Some compilers warn about not following the
guideline,
but others don't.

Your make_foo() function is a good starter, but, as you mustnot depend on
non-statics
in MyClass, make make_foo() static if possible. (And think twice, if it's
not possible)
Making make_foo() a non-member might even be the option I would choose (And
of
course, change the type of the parameter to const std::string&)

Hm... While thinking about this "calling make_foo() twice" in your example,
I thought
about the following "sollution":

Foo make_foo(const std::string& name) {
//...
}

class MyClass {
Bar bar; // Bar has constructor with a const Foo& parameter
Foo foo;

MyClass(const std::string& name) : bar(foo(make_foo(name))) { }
}

I think this is highly undefined behaviour, because there are two
contradicting concepts:
1. parameters are evaluated, before a call is actually performed
2. members are initialized from top to bottom

As of rule 1, first make_foo() should be called, which in turn is used to
initialize foo, which in
turn is used to initialize bar. // note: foo initialized before bar!
Rule two mandates, that bar must be initialized with foo, then foo will be
initialized.

What is happenig here?

TIA
Norbert
Jul 22 '05 #7

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

4
by: Samuele Armondi | last post by:
Hi, I'm writing some exception class for a project, and I've got a class called BasicException that looks like this: class BasicException { private: std::string Description; int Number; ...
2
by: Tim | last post by:
Please advise if you can. Presumably initialisation of members in member initialisation lists is perfomed by 'C' run-time startup. If the CRT was never started-up would those members be garbage?...
5
by: rossum | last post by:
Either I have found a puzzle, or I am just being stupid. Inside a namespace I have a class with a static const double member. The member is not an int so I cannot initialise it within the class,...
7
by: ank | last post by:
Hi, I was curious about how to define static data member of template class. Should I put the definition in a separate source file or in the same header file as its template class? And when this...
11
by: ziman137 | last post by:
Hi all, I have a question here. What is the rationale behind ISO C++ for Static Member Definition? * ISO C++ forbids in-class definition/initialization of non-constant static member...
8
by: Tim Clacy | last post by:
1) Is this initialising the reference 'u' to the address of the literal '2' or to the address 0x00000002? unsigned const& u = 2; 2) What is the different between the initialisation of 'u'...
4
by: sks | last post by:
hi , i Have a code snippet as follows class ABC { int &r; ABC(int a=0): r(a) {} }; int main() {
5
by: Bryan | last post by:
Hi, Where is the proper place to use a member initialization list, the header or cpp file? Does it make any difference? Also, is there any difference between using a member initialization...
2
by: .rhavin grobert | last post by:
i have (do try to have?) the following... & = breakpoints in debugger // ---------------------------------------------------------------- // cx.h class CX { public: CX(CX* pcx = NULL);...
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome former...
0
by: ryjfgjl | last post by:
In our work, we often need to import Excel data into databases (such as MySQL, SQL Server, Oracle) for data analysis and processing. Usually, we use database tools like Navicat or the Excel import...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.