Shane said:
As previously quoted, 4.1/1 clearly states that an lvalue may not be
used as an rvalue unless it was previously initialized. Apparently,
No, it says it can't if the object to which the lvalue refers is
"uninitialized". I can't find a definition for that term in the
standard, but I think it's fairly clear that in this context they are
using it to mean "having an indeterminate value". This use of this term
here may be a defect. In my opinion, it's very clear in the standard
itself that "initialization" refers to giving a value to an object when
it is created.
int n;
n = 0;
qualifies as initialization for these purposes.
It qualifies as giving it a determinate value, but initialization only
occurs when an object is created.
initialization - giving an object an initial value. Initialization
differs from assignment in that there is no previous value involved.
Initialization is done by constructors.
http://www.research.att.com/~bs/glossary.html
So, do you know the terminology better than Bjarne Stroustrup?
I know that PODs aren't initialized by constructor (indeed, they
needn't be initialized at all, useless as that would be).
Stroustrup seems to be of the opinion that all types have constructors
(though the standard disagrees with him). I believe this has been
discussed here before. See, for example, page 131 of TC++PL3. I think he
was referring to all types here.
Short of
saying that he's wrong, my guess is that he's talking about non-PODs,
which accounts for most types (excluding pointers), and about which
he's entirely correct.
As for PODs, consider the following:
// Assign n to x. (That *is* what it does, no?)
template <typename T> void assign (T &x, T n) { x = n; }
int main () {
int i = 0, j;
assign(i, 0);
assign(j, 0);
i = j;
}
If you're right, then either j isn't initialized and this program is
undefined by 4.1/1, or assign(x, n) performs assignment sometimes and
initialization other times -- all with the same code.
I don't see where you are getting that from. The function clearly does
an assignment. 4.1/1 deals with conversion from an lvalue to an rvalue,
which does not apply in this case. See 8.5.3/5-7:
5 A reference to type "cv1 T1" is initialized by an expression of type
"cv2 T2" as follows:
--If the initializer expression
6
--is an lvalue (but not an lvalue for a bit-field), and "cv1 T1" is
reference-compatible with "cv2 T2," or
--has a class type (i.e., T2 is a class type) and can be implicitly
converted to an lvalue of type "cv3 T3," where "cv1 T1" is refer-
ence-compatible with "cv3 T3" 9) (this conversion is selected by
enumerating the applicable conversion functions (_over.match.ref_)
and choosing the best one through overload resolution
(_over.match_)), then
7 the reference is bound directly to the initializer expression lvalue
in the first case, and the reference is bound to the lvalue result
of the conversion in the second case. In these cases the reference
is said to bind directly to the initializer expression. [Note: the
usual lvalue-to-rvalue (_conv.lval_), array-to-pointer
(_conv.array_), and function-to-pointer (_conv.func_) standard con-
versions are not needed, and therefore are suppressed, when such
direct bindings to lvalues are done. ]
Summarized, when initializing (e.g., through function argument passing)
a reference, if the initializer expression is a lvalue (clearly the case
here) that is reference-compatible with the destination reference type
(also applicable here), the reference is bound directly to the lvalue,
and the usual lvalue-to-rvalue conversion is suppressed. If you need
proof that function argument passing qualifies as initialization, please
see 8.5/1
(It could also
use a better name -- assign_or_initialize, maybe.) More likely,
assign(x, n) performs assignment all the time and initialization
sometimes.
You're free to disagree, I guess. Of course, it doesn't matter what
your opinion (or mine) is; neither of us will learn anything about C++
that we didn't already know before this thread, nor do I think that
either of us will convince the other of his point. To quote somebody:
"Arguing on the Internet is like competing in the Special Olympics...
Even if you win, you're still retarded."
Well, for one thing neither of us is going to win. Which is pretty much
what you said above.
With that, I hereby agree to disagree and resign.
That's a bit premature. Here are a few more quotations to emphasize my
point (that the intent of the standard, if not the precise wording, is
that initialization occurs only at the time of creation):
8.5 Initializers [dcl.init]
1 A declarator can specify an initial value for the identifier being
declared. The identifier designates an object or reference being ini-
tialized. The process of initialization described in the remainder of
_dcl.init_ applies also to initializations specified by other syntac-
tic contexts, such as the initialization of function parameters with
argument expressions (_expr.call_) or the initialization of return
values (_stmt.return_).
The very fact that "Initializers" comes under declarations is a pretty
strong statement about where initialization occurs, I think. The
phrasing of this passage also implies that initialization is done at
object creation.
12.8 Copying class objects [class.copy]
1 A class object can be copied in two ways, by initialization
(_class.ctor_, _dcl.init_), including for function argument passing
(_expr.call_) and for function value return (_stmt.return_), and by
assignment (_expr.ass_). Conceptually, these two operations are
implemented by a copy constructor (_class.ctor_) and copy assignment
operator (_over.ass_).
This again shows the distinction between initialization and assignment
(applied only to classes in this case).
Maybe stronger proof is in there somewhere. I'm kind of tired of looking
for it, though. I'll agree that the standard appears to be not entirely
consistent on this point, but my feeling is that the intent of the
standard is to create a logical distinction between initialization
(which occurs when an object is created) and assignment (which can only
occur when the target already exists).
-Kevin