I guess the gist of your question is about why the second identifier is recognized as identifying the same object as the first, in int i = i;
or int &p = p;
This is defined in [basic.scope.pdecl]/1 of the C++14 standard:
The point of declaration for a name is immediately after its complete declarator and before its initializer (if any), except as noted below. [Example:
unsigned char x = 12;
{ unsigned char x = x; }
Here the second x
is initialized with its own (indeterminate) value. —end example ]
The semantics of these statements are covered by other threads:
Note - the quoted example differs in semantics from int i = i;
because it is not UB to evaluate an uninitialized unsigned char
, but is UB to evaluate an uninitialized int
.
As noted on the linked thread, g++ and clang can give warnings when they detect this.
Regarding rationale for the scope rule: I don't know for sure, but the scope rule existed in C so perhaps it just made its way into C++ and now it would be confusing to change it.
If we did say that the declared variable is not in scope for its initializer, then int i = i;
might make the second i
find an i
from an outer scope, which would also be confusing.