Stroustrup 5.9, exercise 9

A

arnuld

i am unable to think of any solution to this problem :-( :

"Find an example where it would make sense to use a name in its own
initializer."

???
 
A

Alf P. Steinbach

* arnuld:
i am unable to think of any solution to this problem :-( :

"Find an example where it would make sense to use a name in its own
initializer."

???

This question has been discussed before, so presumable googling would help.

As I recall my own example was the only practical usage:

Whatever o = {sizeof(o)};
STATIC_ASSERT( offsetof( Whatever, byteSize ) == 0 );

which sets the first member of o to the struct's size, and
zero-initializes the rest.

Later on, without discussing that question, someone in this group came
up with a "trick" that involved

Whatever o(o);

but I don't recall exactly what that was meant to accomplish.

Oh, wait, it's coming back to me ... I think it was about avoiding
compiler silly-warnings that a declared object was not "used". For the
cases where all the object declaration is meant to accomplish is to do
something in the constructor, and then clean up (undo) in destructor.
 
V

Victor Bazarov

arnuld said:
i am unable to think of any solution to this problem :-( :

"Find an example where it would make sense to use a name in its own
initializer."

???

Not sure what is meant here, but maybe this

SomeType object(&object);

What would SomeType do with its own address? It could store it
to indicate the end of the chain of objects (instead of NULL, for
example).

V
 
A

arnuld

Alf said:
* arnuld:

This question has been discussed before, so presumable googling would help.

As I recall my own example was the only practical usage:

Whatever o = {sizeof(o)};
STATIC_ASSERT( offsetof( Whatever, byteSize ) == 0 );

which sets the first member of o to the struct's size, and
zero-initializes the rest.

Later on, without discussing that question, someone in this group came
up with a "trick" that involved

Whatever o(o);

but I don't recall exactly what that was meant to accomplish.

Oh, wait, it's coming back to me ... I think it was about avoiding
compiler silly-warnings that a declared object was not "used". For the
cases where all the object declaration is meant to accomplish is to do
something in the constructor, and then clean up (undo) in destructor.

well, to my *surprise* this works:

-----------------------------------------
#include<iostream>

int x = x;

int main()
{
return 0;
}


[arch@voodo tc++pl]$ g++ -ansi -pedantic -Wall -Wextra -O test.cpp
[arch@voodo tc++pl]$ ./a.out

----------------------------------------


BUT this did not and i started this post because earlier i tried this:

----------------------------------------
#include<iostream>

int main()
{
int x = x;

return 0;
}



[arch@voodo tc++pl]$ g++ -ansi -pedantic -Wall -Wextra -O test2.cpp
test2.cpp: In function 'int main()':
test2.cpp:6: warning: 'x' is used uninitialized in this function
[arch@voodo tc++pl]$
-----------------------------------



i want to know the WHY

????
 
A

Alf P. Steinbach

* arnuld:
Alf P. Steinbach wrote:
* arnuld:
This question has been discussed before, so presumable googling would help.

As I recall my own example was the only practical usage:

Whatever o = {sizeof(o)};
STATIC_ASSERT( offsetof( Whatever, byteSize ) == 0 );

which sets the first member of o to the struct's size, and
zero-initializes the rest.

Later on, without discussing that question, someone in this group came
up with a "trick" that involved

Whatever o(o);

but I don't recall exactly what that was meant to accomplish.

Oh, wait, it's coming back to me ... I think it was about avoiding
compiler silly-warnings that a declared object was not "used". For the
cases where all the object declaration is meant to accomplish is to do
something in the constructor, and then clean up (undo) in destructor.

well, to my *surprise* this works:

-----------------------------------------
#include<iostream>

int x = x;

int main()
{
return 0;
}


[arch@voodo tc++pl]$ g++ -ansi -pedantic -Wall -Wextra -O test.cpp
[arch@voodo tc++pl]$ ./a.out

----------------------------------------


BUT this did not and i started this post because earlier i tried this:

----------------------------------------
#include<iostream>

int main()
{
int x = x;

return 0;
}



[arch@voodo tc++pl]$ g++ -ansi -pedantic -Wall -Wextra -O test2.cpp
test2.cpp: In function 'int main()':
test2.cpp:6: warning: 'x' is used uninitialized in this function
[arch@voodo tc++pl]$
-----------------------------------



i want to know the WHY

????

That's because namespace scope variables (such as the first one) are
zero-initialized first of all, and only then is the stated
initialization, if any, performed. Which means the first program's x is
guaranteed to be zero, just as if you hadn't specified an
initialization. The specified initialization initializes x with itself,
which is at this point 0 (earlier zero-initialization), so, it's 0.

There is no automatic zero-initialization of automatic variables, like
the one in your second program.

Thus, the second program's initialization initializes x with itself,
which at this point has an /indeterminate/ value, or in other words,
arbitrary bits, garbage. So the compiler helpfully offers a warning.
You're allowed to do that, or just about anything, but since it's
/usually/ a mistake, the compiler warns about it.
 
R

Ralph D. Ungermann

Alf said:
* arnuld:
well, to my *surprise* this works:
#include<iostream>

int x = x;
BUT this did not and i started this post because earlier i tried this: [...]
int main()
{
int x = x;
i want to know the WHY

That's because namespace scope variables (such as the first one) are
zero-initialized first of all, and only then is the stated
initialization, if any, performed.

I thought, that zero initialization takes place *by default*, i.e. only
if there is no explicit initialization.
I'd expect undefined behavior, because the right hand side is not
initialized yet.
There is no automatic zero-initialization of automatic variables, like
the one in your second program.
Agreed.

Thus, the second program's initialization initializes x with itself,
which at this point has an /indeterminate/ value, or in other words,
arbitrary bits, garbage. So the compiler helpfully offers a warning.
Agreed.

You're allowed to do that, or just about anything, but since it's
/usually/ a mistake, the compiler warns about it.

I'd expect, that reading garbage leads to undefined behavior.

I have no standard to look it up, but replacing `int' with
`std::string', my compiler (g++-3.3 -ansi -pedantic -Wall) emits no
diagnosis at all, but the first (static) program causes a "Segmentation
fault", and the second (auto) prints "Aborted". Here's my test code:

#include<iostream>
#include<string>

//std::string stat_s = stat_s; // "Segmentation Fault"

int main()
{
// std::cout << "stat: " << stat_s << std::endl;
std::string auto_s = auto_s;
std::cout << "auto: " << auto_s << std::endl; // "Aborted"
}



My advice to arnuld:
1. Don't do never ever use the _value of x_ in the initializer of x.
2. If you do, don't expect any specific behavior from your compiler. It
may emit a diagnosis, produce illegal instructions, or delete your emails.

But the original question was about using the _name of x_ in its own
initializer. As the value is still undefined, I can imagine only two
formal cases :
1. sizeof( x ) -- but you can use sizeof with the type of x as well here.
2. &x, (or &x.member), which is well defined (the ampersand may be
hidden, if the ctor expects a reference). But remember: you may store
the address, but you must not yet dereference it.
 
A

Alf P. Steinbach

* Ralph D. Ungermann:
Alf said:
* arnuld:
well, to my *surprise* this works:
#include<iostream>

int x = x;
BUT this did not and i started this post because earlier i tried this: [...]
int main()
{
int x = x;
i want to know the WHY

That's because namespace scope variables (such as the first one) are
zero-initialized first of all, and only then is the stated
initialization, if any, performed.

I thought, that zero initialization takes place *by default*, i.e. only
if there is no explicit initialization.

No, it takes place before any dynamic initialization.

However, under certain circumstances the compiler is allowed to replace
the dynamic initialization with static initialization (an optimization).

I'd expect undefined behavior, because the right hand side is not
initialized yet.

It is.
 

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,763
Messages
2,569,563
Members
45,039
Latest member
CasimiraVa

Latest Threads

Top