J
James Kanze
"Francesco S. Carta" <[email protected]>The initialization involves an lvalue-to-rvalue conversionint i = i;
As far as I understood this (see my other post in this
thread for further lucubrations), if "i" has static
lifetime, then "i" will be initialized to zero and then [*]
copy-created from zero again - well defined behaviour then.
If it has not static lifetime then it gets some junk value
- and that /value/ would be undefined, of course, but the
object is still valid and the implementation should not be
free to invoke UB and to format my hard disk if I happen to
use an non-itialized or junk-initialized integer for
something trivial as printing it out
of object i, that is at that point not initialized. The
Standard explicitly states that being UB, so that's it.
"Should"s may still play on the QoI field certainly,
conforming implementation has unlimited license to do any
good thing as bad.
I suppose your reference goes to the non-static i instance,
and in such case I'm not at all sure whether it is UB or not,
although it might very well be - I'd like to be referenced
with the appropriate section of the standard in order to
clarify this.
It's not a clear as it could be in the C++ standard, but you get
it indirectly: in §3.9.1/1, there is the guarantee that "For
character types, all bits of the object representation
participate in the value representation. For unsigned character
types, all possible bit patterns of the value representation
represent numbers. These requirements do not hold for other
types." In other words, except for unsigned character types
(unsigned char, and possibly char, depending on the
implementation), trapping representations are possible. (The C
standard is a lot clearer in this respect.) If the "random
initialization" corresponds to a trapping representation, then
anything is possible. (I think that in one modern
implementation, certain bits must be 0, or the hardware will
treat the number as a pointer or as floating point.)
About the static lifetime instance, times ago I was presented
by James Kanze with an example of how to instantiate a
singleton using exactly this
peculiarity:http://groups.google.com/group/comp.lang.c++/msg/c5707d36e886fe3e
Before going on, I'd have to ask one thing: is it guaranteed
that operator ! evaluates true when applied to a
zero-initialized pointer?
Yes, but it's a lot cleaner to compare it to 0 or to NULL.
In practice I want to know if given the following:
static int* p;
!p == true
As long as no one has modified the value.
If it is guaranteed - and I think so - then I dare to claim that (I
can't believe I'm starting over arguing about the standard, but anyway):
1)
int i = i;
is well defined at global scope
2)
static int i = i;
is well defined in any scope where the statement is legal
Both are true, as long as no one else has modified i. Both are,
however, uninteresting.
3)
int* get_p();
int* p = get_p();
int* get_p() {
if(!p) p = new int;
return p;
}
is well defined at global scope
It's an established idiom.
4)
given:
int* get_p(int* p) {
if(!p) p = new int;
return p;
}
then:
static int* p = get_p(p);
is well defined in any scope where the statement is legal
Are my claims correct?
Yes. It's one frequent idiom used in the initialization of
singletons.