If the referece is known by the compiler to always refer to a single particular object/item, then the compiler could certainly optimize away the indirection.
However, most references are in fact bound at runtime. Even if a particular instance of a reference can't be rebound, different executions of a particular scope or different instances of an object that contains reference members may run with the reference bound to a different object for each of those instances. Using indirection is a conventient way for the compiler to deal with this.
The situation where a reference is only ever bound to a single thing might be relatively infrequent enough that compilers might not look for the optimization - especially since it may be that the optimization wouldn't be a noticable gain in most cases.
Also, I suspect you're not turning on compiler optimizations - using your code and calling various functions with y
and i
and their addresses, a quick test in VC++ 2005 with optimizations on shows that the compiler is not implementing i
as a pointer, but as a true alias for y
(ie., whenever passing i
or &i
, the compiler uses the address of y
directly).
If you're looking at the debug output of a compiler, it shouldn't surprise you that it always treats a reference as a pointer behind the scenes.