A is now another name for B. Anything we do to A, we're doing to B, because they're the exact same single object. A is not a copy of B. A is B. It's another name for it. I think some languages might call this an alias.
People will often start arguing about how references are a kind of pointer underneath and various implementation details, but that's simply how the compiler chooses to make it work. The implementation details are nice to know, but they're not the definition.
I'll let someone who knows more about compiler internals than me present a physical example of some implementation. Given that references work across scopes (which is where your simple examples break down), I think that doing it by handing around memory addresses is a reasonable way to do it (which is effectively "by pointers" although once you get to the level of assembly, the higher level concepts like that stop making as much sense).
in simple terms, a reference is just another name for an existing variable, it is not "stored" anywhere in the memory, and it can be used the same way as the original variable.
internally by compiler references are addresses to existing variables and their names (addresses) are replaced by "dereferenced pointer" to the existing variable, so you don't have to use * dereference operator, anyway you should not worry about how compiler treats them.
they are useful in function parameter list, because, objects will not be copied only addresses will be passed and compiler will dereference the address to the actual object.
the & sign next to reference name or reference type is confusing part, what this actually means is as said above, it means that it takes an address or passes an address, but you don't have to worry about dereferencing the address, because that's compilers' job.
knowing that it becomes obvious why references need to be initialized right away, it's because address must be known in order to bind an object to the reference name.