Pointers are values. Valuea ars values. Values have a unique identity, require storage.
References are not values. References have no identity. If we have:
int x=0;
int& y=x;
int& z=x;
both y
and z
are references to x
, and they have no independent identity.
In comparison:
int x=0;
int* py=&x;
int* pz=&x;
both py
and pz
are pointers at x
, and they have independent identity. You could modify py
and not pz
, you can get a size of them, you can memset them.
In some circumstances, at the machine code level, references are implemented the same way as pointers, except certain operations are never performed on them (like reaiming them).
But C++ is not defined in terms of machine code. It is defined innterms of the behaviour of an abstract machine. Compilers compile your code to operations on this abstract machine, which has no fixed calling convention (by the standard), no layout for references, no stack, no heap, etc. It then does arbitrary transformations on this that do not change the as-if behaviour (a common one is single assignment), rearranges things, and then at some point emits assembly/machine code that generates similar behaviour on the actual hardware you are running on.
Now the near universal way to compile C++ is the compilation unit/linker model, where functions are exported as symbols and a fixed ABI calling convention is provided for other compilation units to use them. Then at link stage the compilation units are connected together.
In those ABIs, references are passed as pointers.