std::string name4 = name4;

J

James Kanze

"Francesco S. Carta" <[email protected]>
int 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 :)
The initialization involves an lvalue-to-rvalue conversion
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.
 
F

Francesco S. Carta

Francesco S. Carta said:
int 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 :)

The initialization involves an lvalue-to-rvalue conversion 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,
Yes.

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.

Guess you could look up the precisely referred section. :-(

I'm not so sure about how to parse the above... if you mean that I could
_now_ look up the section, it seems that you already did it for me, if
you meant I could look it up _before_ (i.e. on the base of your previous
post) well I couldn't because it was not clear to me which section you
were referring to... whatever, feel free to skip this one.
4.1 Lvalue to rvalue conversion [conv.lval]

1 An lvalue (3.10) of a nonfunction, nonarray type T can be converted to
an rvalue. If T is an incomplete type, a program that necessitates this
conversion is illformed. If the object to which the lvalue refers is not
an object of type T and is not an object of a type derived from T, or if
the object is uninitialized, a program that necessitates this conversion
has undefined behavior. If T is a nonclass type, the type of the rvalue
is the cvunqualified version of T. Otherwise, the type of the rvalue is
T. 49)

Thank you for reporting the reference.

By now it's quite ascertained, from the above, that a non static
lifetime "int i = i;" instantiation is UB, although I consider it just
as trivial UB as it would be to print out some junk value contained in
an uninitialized variable. I'll try to get my hands on my copy of the
standard once more and I'll try to get a better understanding of this.
Yes, it should. "zero" init means semantic zero for any type. An
non-local objects are subject to value-initialization, so the above case
does not apply. If you fo after it make sure to use the 2003 text as it
changed from the '98 one.

Thank you for the clarification about the standard version to refer to,
my copy should be the 2003 one if my memory serves me well.
 
F

Francesco S. Carta

"Francesco S. Carta"<[email protected]>
int 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 :)
The initialization involves an lvalue-to-rvalue conversion
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.)

Thank you for the information, now all of this is making more sense: I
was inclined to consider this UB as a trivial one, but the chance of
trapping representation completely change the light under which I look
at this now.
Yes, but it's a lot cleaner to compare it to 0 or to NULL.

I personally consider "!p" just as clean as "p == 0", but of course it
is just matter of tastes.
As long as no one has modified the value.




Both are true, as long as no one else has modified i. Both are,
however, uninteresting.

Agreed ;-)
It's an established idiom.



Yes. It's one frequent idiom used in the initialization of
singletons.

Thanks a lot for confirming my claims, luckily I correctly recalled the
conclusions of the old thread I linked above.
 
G

Gennaro Prota

No, although a warning might be appropriate.


Does it? It really depends on what you do with the variable.
Consider something like:

class List
{
List* next;
public:
List(List& olderInstance) : next( &olderInstance ) {}
// ...
};

Given something like this,
List aList( aList );
poses no problems. (Provided, e.g. that the code following the
pointers recogizes a list pointing to itself as the end of the
list.)

Referring to your "does it?", it's the same old story: as soon
as you do something just a little "unusual" the standard isn't
able to provide an answer. I filed this DR, for instance:

<http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#453>

from which B. Stroustrup split another one:

<http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#504>

But it doesn't really matter whether they have "fixed" it or
not: the standard will still be unable to provide clear answers
to such questions (even if the answer to /one/ particular
question may become clear after years of attempted rewordings
and discussions). Once William Miller told me that in his long
experience with the PL/I standard (which is written using a
formal methodology) he had never had an occasion where he had a
question that could not be answered definitively from the
standard itself.

Makes one think, I suppose.
 
L

Lynn McGuire

It's always possible to complicate the language to prohibit stupid code.
With MS compilers:

std::string s = s; // no warning
int i = i; // C4700: uninitialized local variable 'i' used

I expect the C4700 behavior for all types, not just the hardware types. I
wonder if this is possible to turn on in the MS compilers.

Thanks for all the relies and analysis,
Lynn
 
Ö

Öö Tiib

There is nothing wrong with "delete this" if you know what you are doing.
If you know what you are doing "delete this" is usually *not* a bug.

I trust that there is nothing wrong with "T a = a" as well when you
know what you are doing. I do not know neither situation where "delete
this" is best solution nor where "T a = a" is best solution. "delete
this" smells for reference counting and "T a = a" smells for cv
qualifier detection.

So ... both may be likely details for some bigger (platform specific?)
(template wizardry?) spells. The only problem is that i do not know
these spells.
 
J

Juha Nieminen

Francesco S. Carta said:
This is equally "valid" (in syntax, but still undefined behavior):

int 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 :)

In the case of a primitive type (such as int) I should have probably
used the term "implementation-defined" rather than "undefined behavior".
 
B

Balog Pal

I trust that there is nothing wrong with "T a = a" as well when you
know what you are doing. I do not know neither situation where "delete
this" is best solution nor where "T a = a" is best solution.

Seem like many of us do. There are fine systems where an onject handles its
lifetime, and that is the most beneficial way.
"delete this" smells for reference counting

I've see it used more without reference counts.
and "T a = a" smells for cv qualifier detection.

How could it detect cv qualifier? And whatever 'detection' it would do,
how the first 'a' can be relevant? T b = a; would serve the same purpose if
SFINAE is the thing we're after.
So ... both may be likely details for some bigger (platform specific?)
(template wizardry?) spells. The only problem is that i do not know
these spells.

i still see one as as useful proven tool in sensible designs, and the other
as pure nonsense producing UB and gaining nothing. Instances likely to be a
typo.
 
B

Balog Pal

Juha Nieminen said:
In the case of a primitive type (such as int) I should have probably
used the term "implementation-defined" rather than "undefined behavior".

Why? The standard clearly states it is UB. In practice who ever saw an
implementation defining the effect of uninitialized access? I worked on a
ton of platforms and never saw one. Sure you can make guesses on the
produced assembly but that is not ImpDef, merely heuristic.
And one I'd not advise build on!
 
S

sankalp srivastava

Well, that is too bad.

Thanks,
Lynn

this is a legal operation , although stupid ...the variable is defined
as soon as it's definition is seen and that is before the equality
operator .
This calls for an invocation of a copy constructor to initialize and
make a bitwise copy of the object from the object on the LHS .
This bitwise copy cannot be carried out here because the object has
not been created till now ..hence on runtime.

not that the scope has not much to do in this case because the scope
resolution rules for C++ , will nautrally , first search for the std
as the definition is qualified by that and then , look for other
subsequent scopes and finally the global scope .

There's no compile time error in the code , although this is a runtime
error
On the other hand , has this been a built-in type , it's a legal and
fine running although uninituitive code . The built in types , do not
require a constructor or copy constructor , hence this will run just
fine ..


Thanks
Sankalp
 
J

Juha Nieminen

Balog Pal said:
In practice who ever saw an
implementation defining the effect of uninitialized access?

I would say that even a "the value of an uninitialized int is not
guaranteed" is a definition.
 
J

James Kanze

Yes, what i meant was self-initializing like "T a = a;" is like
"delete this" legitimate, but usually a bug.

In well written code, I suspect that most deletes are "delete
this". If you're writing in an object oriented style, it's the
most logical way of doing things, and if you're not, then you're
probably not doing that much allocating (and deleting) anyway.
Someone surely can construct meaningful usage for "T a = a;"
too.

Sure. I did else-thread. But the case is fairly rare, where as
"delete this" is very frequent.
 
J

James Kanze

There is nothing wrong with "delete this" if you know what you
are doing.

And if you don't know what you're doing, avoiding "delete this"
isn't going to make your code work any better:).
If you know what you are doing "delete this" is usually *not*
a bug.

It's a design issue. In the past, I've found that most of my
delete's are delete this, but it depends a lot on the
application.
 
J

James Kanze

I trust that there is nothing wrong with "T a = a" as well when you
know what you are doing. I do not know neither situation where "delete
this" is best solution nor where "T a = a" is best solution. "delete
this" smells for reference counting and "T a = a" smells for cv
qualifier detection.

"delete this" has nothing to do with reference counting. It's
just good OO design. An object has behavior, and part of that
behavior is destroying itself when the time comes. (In
practice, of course, the issues are more complicated, and in
some cases, the actual delete will be done by a transaction
manager or some such. But the decision is usually that of the
object.)
 
F

Francesco S. Carta

[...]
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.
I personally consider "!p" just as clean as "p == 0", but of
course it is just matter of tastes.

Not really. It's the difference between saying what you mean,
and obfuscating code behind some unintuitive implicit
conversions.

In both cases I would be saying what I meant, and the fact that "!p"
could be unintuitive is subjective as well - I'm sure that any
programmer with some decent experience recognizes the meaning of that
statement at a glance. Granted, writing "p == 0" is a better
eye-catcher, and shall I find myself in a context where that's the
preferred form, I would use it without any problem.
 
K

Kai-Uwe Bux

James said:
[...]
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.
I personally consider "!p" just as clean as "p == 0", but of
course it is just matter of tastes.

Not really. It's the difference between saying what you mean,
and obfuscating code behind some unintuitive implicit
conversions.

You are correct that it is not a matter of taste. However, I disagree with
your analysis as to what the choice between the different coding options is
about.

I think, it is very much a matter of local coding standards. Code is meant
to communicate intent and should express it in the most direct way (I share
the implicit assumption, you also seem to make). What this way is, however,
depends on what your community members (the intended readers of your code)
expect / are used to / prefer / have used many times thereby establishing
precedence. The language allows both forms and guarantees the behavior for
either one. Which one is more appropriate depends on the intended readers
and should not be answered in the abstract.


Best

Kai-Uwe Bux
 
F

Felix Palmen

* James Kanze said:
Not really. It's the difference between saying what you mean,
and obfuscating code behind some unintuitive implicit
conversions.

How is "p == 0" what I mean? "p == NULL" or "p == nullptr" would be more
like what I mean. Sure, a pointer IS an integer, but semantically, it is
a big difference for me. In my opinion, "!p" is much more intuitive and
closer to what I mean: A pointer that doesn't have a value, so it is NOT
really a (valid) pointer.

Regards, Felix
 
Ö

Öö Tiib

"delete this" has nothing to do with reference counting.  

I proposed reference counting. It was because maybe there is reason in
cases of objects with shared
ownership. So it felt some sort of improvement or optimization over
shared_ptr.
It's
just good OO design.  An object has behavior, and part of that
behavior is destroying itself when the time comes.  (In
practice, of course, the issues are more complicated, and in
some cases, the actual delete will be done by a transaction
manager or some such.  But the decision is usually that of the
object.)

Now i have yes, 3 replies that this is not the case. It is therefore
self-owned object? I avoid self-owned objects. It may be is good OO,
but turns things unnecessarily complex. In my (simplified and not that
good?) OO design everything should belong to something. I have not met
a good reason for something that is both self-owned and not unique.
 
J

James Kanze

Now i have yes, 3 replies that this is not the case. It is therefore
self-owned object?

The real question is whether ownership even has a meaning. An
object is an autonomous entity, with its own behavior. It
doesn't (necessarily, at least) "belong" to any other object.
I avoid self-owned objects. It may be is good OO, but turns
things unnecessarily complex.

Just the opposite. If you forget about ownership, and consider
that an object has responsibilities, and that one of those
responsibilities is to delete itself when it no longer has any
reason to continue to exist, it simplifies a lot of things. (Of
course, a lot depends on the application. If you have complex
transactions, which have to be atomic, it's very difficult to
roll back a deleted object. So regardless of who makes the
decision to delete---the object itself or some other
object---the "delete" will take the form of a request to the
transaction manager, who will do the actual delete in the commit
phase.)
In my (simplified and not that good?) OO design everything
should belong to something. I have not met a good reason for
something that is both self-owned and not unique.

I've yet to find a good reason why an autonomous object should
belong to anything. This whole concept of ownership has been
artificially introduced to C++ in order to pretend to manage
memory issues, but it really doesn't make any sense at a larger
level. (Most of the time, of course. There are exceptions.)

This is independent of who does the delete---in my parenthetical
example above, the transaction manager certainly doesn't own the
object, even if it does do the actual delete in its commit
phase. (And the object lifetime can obviously be more than
a single transaction.)
 

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

Forum statistics

Threads
473,770
Messages
2,569,583
Members
45,072
Latest member
trafficcone

Latest Threads

Top