Questionable compiler warning

T

Thomas Heinz

Hi

Consider the following program.

class T
{
int b, a;
T(int a, int b) : a(a), b(b) {}
};

g++ -Wall -c test.cc produces the following warning.

test.cc: In constructor `T::T(int, int)':
test.cc:3: Warnung: `T::a' will be initialized after
test.cc:3: Warnung: `int T::b'
test.cc:4: Warnung: when initialized here


Obviously, g++ likes the initialization order to be
the same as the declaration order of the corresponding
variables. Does anyone know whether/why it is critical
for them to have the same order?

Thanks for your help.


Regards,

Thomas
 
J

John Harrison

Thomas Heinz said:
Hi

Consider the following program.

class T
{
int b, a;
T(int a, int b) : a(a), b(b) {}
};

g++ -Wall -c test.cc produces the following warning.

test.cc: In constructor `T::T(int, int)':
test.cc:3: Warnung: `T::a' will be initialized after
test.cc:3: Warnung: `int T::b'
test.cc:4: Warnung: when initialized here


Obviously, g++ likes the initialization order to be
the same as the declaration order of the corresponding
variables. Does anyone know whether/why it is critical
for them to have the same order?

It isn't, but some people wrongly assume that the order of initalisation is
the same as the order in the initialisation list. So I would imagine the
reason for the warning is just to make sure people don't make that mistake.

john
 
T

Thomas Heinz

Hi John
It isn't, but some people wrongly assume that the order of initalisation is
the same as the order in the initialisation list. So I would imagine the
reason for the warning is just to make sure people don't make that mistake.

There is a misunderstanding. My question should rather be:

"Obviously, g++ likes the initialization order to be
the same as the declaration order of the corresponding
members." (not variables in the init. list).

However, I think one reason why the initialization order is
fixed by some means is that there can only be one destruction
order.


Regards,

Thomas
 
V

Victor Bazarov

Thomas said:
Hi John



There is a misunderstanding. My question should rather be:

"Obviously, g++ likes the initialization order to be
the same as the declaration order of the corresponding
members." (not variables in the init. list).

However, I think one reason why the initialization order is
fixed by some means is that there can only be one destruction
order.

Yes, but that's not the essence of your statement, nor is it the essence
of John's reply. The reason for the warning is to _remind_ the user that
the order [of initialisation] is going to be the same as the declaration,
and not the order of initialisers in the list.

It's not that g++ "likes" it to be the same, it's more in line with g++
trying to keep the user from making the mistake. If g++ _liked_ it to be
specific, then it would probably issue an error instead of a warning.

Sorry to butt in on the conversation, just thought I'd add my $0.02...

V
 
N

Nithyanandham M

Thomas said:
class T
{
int b, a;
T(int a, int b) : a(a), b(b) {}
};

g++ -Wall -c test.cc produces the following warning.

test.cc: In constructor `T::T(int, int)':
test.cc:3: Warnung: `T::a' will be initialized after
test.cc:3: Warnung: `int T::b'
test.cc:4: Warnung: when initialized here


Obviously, g++ likes the initialization order to be
the same as the declaration order of the corresponding
variables. Does anyone know whether/why it is critical
for them to have the same order?
The definite initialization order is followed by g++, not just because
it likes, but because the C++ standard says so.

Here is an excerpt from the C++ standard for the same:

<C++STD>
12.6.2 - Initializing bases and members [class.base.init]
5.
Then, nonstatic data members shall be initialized in the order they were
declared in the class definition (again regardless of the order of the
mem-initializers).
</C++STD>
 
G

Gary Labowitz

Thomas Heinz said:
Hi

Consider the following program.

class T
{
int b, a;
T(int a, int b) : a(a), b(b) {}
};

g++ -Wall -c test.cc produces the following warning.

test.cc: In constructor `T::T(int, int)':
test.cc:3: Warnung: `T::a' will be initialized after
test.cc:3: Warnung: `int T::b'
test.cc:4: Warnung: when initialized here


Obviously, g++ likes the initialization order to be
the same as the declaration order of the corresponding
variables. Does anyone know whether/why it is critical
for them to have the same order?

As pointed out elsewhere, the standard calls for initialization in
declaration order. This is to allow for use of one variable in initializing
another. Suppose b was always (3*a) more than the value provided for b
(fancy encryption!). Your code might be:

....
T(int a, int b) : a(a), b(a*3 + b) {}
....
Can you see that this won't work because b will be initialized first, using
an uninitialized a? That's why the warning was issued.
Changing the order in the declaration would allow this initialization list
to work properly.
 
T

tonci.tomic

Thomas Heinz said:
...
Obviously, g++ likes the initialization order to be
the same as the declaration order of the corresponding
variables.

It's not that g++ "likes" that. It is carved in standard
 
G

Gary Labowitz

A side note (and New Topic):
While the parameter list in a constructor can use the same identifiers as
the class member names, it is probably a bad habit to get into since it will
bite you if used for methods. I recommend using some convention to identify
parameters as different from the class members, say
T(int Ia, int Ib) : a(Ia), b(Ib) {}
or
T(int newA, int newB) a(newA) b(newB) {}
etc.
 
A

Andrey Tarasevich

Thomas said:
Consider the following program.

class T
{
int b, a;
T(int a, int b) : a(a), b(b) {}
};

g++ -Wall -c test.cc produces the following warning.

test.cc: In constructor `T::T(int, int)':
test.cc:3: Warnung: `T::a' will be initialized after
test.cc:3: Warnung: `int T::b'
test.cc:4: Warnung: when initialized here


Obviously, g++ likes the initialization order to be
the same as the declaration order of the corresponding
variables.

Yes. That's what the language standard requires it do do.
Does anyone know whether/why it is critical
for them to have the same order?

It is required by the standard. As for being "critical"... I'd say you
should ask yourself whether the initialization order is critical in your
particular case. And if it is, you should either carefully keep the
member declarations in proper order (which is not always possible) or
move certain initializations from the initializer list to the
constructor's body.
 
A

Arijit

Thomas Heinz said:
Hi

Consider the following program.

class T
{
int b, a;
T(int a, int b) : a(a), b(b) {}
};

g++ -Wall -c test.cc produces the following warning.

test.cc: In constructor `T::T(int, int)':
test.cc:3: Warnung: `T::a' will be initialized after
test.cc:3: Warnung: `int T::b'
test.cc:4: Warnung: when initialized here


Obviously, g++ likes the initialization order to be
the same as the declaration order of the corresponding
variables. Does anyone know whether/why it is critical
for them to have the same order?

Thanks for your help.


Regards,

Thomas


The initialization order followed is the declaration order,
and not the order used in the constructor. Otherwise, you could
write two different constructors that initialize the variables
in two different orders. This is usually not important and
you can ignore this warning almost always. However, in special
cases this can make a difference. g++ generates the warning in
case you expect a to be initialized before b.

-Arijit
 
T

Thomas Heinz

Hi Gary
...
T(int a, int b) : a(a), b(a*3 + b) {}
...
Can you see that this won't work because b will be initialized first, using
an uninitialized a? That's why the warning was issued.
Changing the order in the declaration would allow this initialization list
to work properly.

class T
{
int b, a;
T(int a, int b) : a(a), b(a*3 + b) {}
};

is equivalent to

class T
{
int b, a;
T(int _a, int _b) : b(_a*3 + _b), a(_a) {}
};

and not to

class T
{
int b, a;
T(int a, int b) : b(T::a*3 + T::b), a(T::a) {}
};


Hence, in your case b is initialized using the
constructur parameter a and not the member a.


Regards,

Thomas
 
A

Ali Cehreli

A side note (and New Topic):
While the parameter list in a constructor can use the same identifiers
as the class member names, it is probably a bad habit to get into since
it will bite you if used for methods.

Good advice!

It is probably more surprising and risky in the constructor. Consider
needing to move the initialization of a member into the body of the
constructor in the future for some reason. This time, not the member,
but the constructor argument would be assigned:

struct S
{
int i;

explicit S(int i)
:
i(1) // <-- initialize member
{
i = 2; // <-- assign to argument
}
};

#include <iostream>

int main()
{
S s(0);
std::cout << s.i << '\n';
}
I recommend using some convention
to identify parameters as different from the class members, say
T(int Ia, int Ib) : a(Ia), b(Ib) {}
or
T(int newA, int newB) a(newA) b(newB) {}
etc.

One of the popular conventions is to append an underscore to the
member name:

class C
{
int value_;
/* ... */
};

I find this kind of name decoration very helpful especially in the
implementation files (.cpp, .cc, etc) when I am trying to figure out
where an object is defined. The appended underscore makes me see right
away that the object is a member.

Otherwise, I would need to search back higher in the scopes to see
where the object was introduced. Only after not finding it that way, I
would realize that it might be a member.

Ali
 
G

Gary Labowitz

Thomas Heinz said:
Hi Gary


class T
{
int b, a;
T(int a, int b) : a(a), b(a*3 + b) {}
};

is equivalent to

class T
{
int b, a;
T(int _a, int _b) : b(_a*3 + _b), a(_a) {}
};

and not to

class T
{
int b, a;
T(int a, int b) : b(T::a*3 + T::b), a(T::a) {}
};

Hey, right you are. Thanks. That's what I meant.
 

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,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top