Conceptually, in your first case what happens is that the same variable has two labels: b
, visible within the scope of main()
; and a
, visible within the scope of fn
.
You don't have to worry about what the compiler does "behind the scenes" to implement this concept.
If you mentally promote the compiler's "behind the scenes" actions to actually being imagined principles of C++, e.g. "the reference is a pointer in disguise", then it leads you to get confused about what is actually a pretty simple concept: the ability to give multiple names to a variable.
It is nothing special being a function parameter; e.g. you could write in main()
:
int a;
int &c = a;
which is exactly equivalent to:
int c;
int &a = c;
In both cases there is an int
variable with two labels, a
and c
.