int foo = foo;
compiles.
Which part of the C++ standard allows this?
-
Related: http://stackoverflow.com/questions/5450633/c-what-does-this-mean-int-foo-foo-4 – Lightness Races in Orbit May 31 '11 at 17:47
-
Also see [Does initialization entail lvalue-to-rvalue conversion? Is `int x = x;` UB?](http://stackoverflow.com/q/14935722/1708801) and [Has C++ standard changed with respect to the use of indeterminate values and undefined behavior in C++14?](http://stackoverflow.com/q/23415661/1708801) – Shafik Yaghmour Sep 22 '15 at 15:27
2 Answers
3.3.1 Point of declaration [basic.scope.pdecl]
The point of declaration for a name is immediately after its complete declarator (clause 8) and before its initializer (if any),
The behaviour is well defined if the declaration is at file scope. If you have the declaration at function scope and if you use foo
later on [which would be initialized to some unspecified value in that case] the behaviour would be undefined.

- 91,295
- 49
- 239
- 345
-
4I would +1 but you've completely failed to mention that the OP's program has undefined behaviour and _should not be used_. – Lightness Races in Orbit May 31 '11 at 14:40
-
5@Tomalak: The code *might* have UB, but doesn't necessarily. The OP seems fully aware that it's not something that should really be used, and is curious about the purely academic point of why it compiles at all. – Jerry Coffin May 31 '11 at 14:43
-
@Tomalak : Not necessarily UB. OP has not specifically mentioned whether the declaration is at file scope or at function scope? – Prasoon Saurav May 31 '11 at 14:45
-
1@Prasoon: `s/program has/program may have/`; `s/should not/possibly should not/`. – Lightness Races in Orbit May 31 '11 at 14:48
-
1Using `foo` "later on" doesn't matter; the initialization itself invokes UB! Does it not? – Lightness Races in Orbit May 31 '11 at 14:54
-
1@Prasoon: Right, and he uses it in the initialization. He's initializing `A` with the uninitialized `B` (and both `A` and `B` happen to be the same object). – Lightness Races in Orbit May 31 '11 at 14:56
This?
int main() {
int foo = foo;
}
The object foo
does exist after the =
, according to [basic.scope.pdecl]
:
The point of declaration for a name is immediately after its complete declarator (clause 8) and before its initializer (if any).
However, the program as a whole is undefined, because you use (on the RHS) an uninitialised value:
int x = x;
Here [..]x
is initialized with its own (indeterminate) value.
And:
Though "inferred and ill-specified" by the standard, an lvalue-to-rvalue conversion is performed on the RHS expression foo
.
And ([conv.lval]
):
An lvalue (3.10) of a non-function, non-array type T can be converted to an rvalue. If T is an incomplete type, a program that necessitates this conversion is ill-formed. 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.
With proper warning levels, you will get told about it; however, programs invoking Undefined Behaviour are allowed to compile. They just can do anything at all when you run them.
Or, what about this?
int foo = foo;
int main() {}
Notice that foo
is a "global". These are zero-initialised as a first step, according to [basic.start.init]
:
Objects with static storage duration (3.7.1) shall be zero-initialized (8.5) before any other initialization takes place.
So you'll get an int foo
with value 0; it's valid, at this point, as per [basic.scope.pdecl]
above, and as per [stmt.decl]
:
The zero-initialization (8.5) of all local objects with static storage duration (3.7.1) is performed before any other initialization takes place. [..]
You then value-initialise it to foo
(itself), i.e. 0.
This is well-defined... if a little cryptic.
In the interests of thoroughness, here's a third and final case:
int foo = 42;
int main() {
int foo = foo;
}
Sadly, this is the same as the first case. Since the local foo
is already declared and in scope by the time the initializer is evaluated, the initializer uses the local foo
and you're still stuck with the Undefined Behaviour. The global foo
is not used.

- 1
- 1

- 378,754
- 76
- 643
- 1,055
-
1
-
@Jerry: There are no globals in my program. If there are globals in the OP's program (or if his `foo` declaration happens at namespace scope), he needs to state this because it completely changes the question. – Lightness Races in Orbit May 31 '11 at 14:42
-
@Jerry: OK. I'll add a clause for that case, then, too. – Lightness Races in Orbit May 31 '11 at 14:46
-
@Jerry: Well it wasn't without assistance, was it? :) – Lightness Races in Orbit May 31 '11 at 14:49
-
@Tomalak: no, but that's life. One of the hallmarks of a good programmer (or almost anything else) is being willing and able to accept assistance... – Jerry Coffin May 31 '11 at 14:50
-
-
both the answers are very good but I accepted prasoon saurav's answer because he was the first to post the correct quote from the standard. – Rohan May 31 '11 at 14:54
-
@Tomalak: does the Standard says that the initialization is UB ? (local case). It makes sense, but I don't recall any specific. – Matthieu M. May 31 '11 at 15:33
-
Maybe your examples would be even more complete if you show what happen with something else than basic types, like a structure? – Klaim May 31 '11 at 15:39
-
-
-
tomalak, clause 4.1 lvalue-to-rvalue conversion says it's UB (IIRC, don't have the spec at hands currently). Notable, it's also UB for `unsigned char`. – Johannes Schaub - litb May 31 '11 at 16:23
-
@litb: Yep it says that; but is there such a conversion here? – Lightness Races in Orbit May 31 '11 at 16:29
-
-
@litb: The expression `foo` is converted to an rvalue for use on the RHS of the full statement? – Lightness Races in Orbit May 31 '11 at 16:33
-
@Tomalak, @Johannes: Thanks for the citation, I didn't thought about checking the conversion rules! – Matthieu M. Jun 01 '11 at 06:04