I once landed an interview and was asked what the purpose of assigning a variable by reference would be (as in the following case):
int i = 0;
int &j = i;
My answer was that C++ references work like C pointers, but cannot assume the NULL value, they must always point to a concrete object in memory. Of course, the syntax is different when using references (no need for the pointer indirection operator, and object properties will be accessed via the dot (.) rather than the arrow (->) operator). Perhaps the most important difference, is that unlike with pointers, where you can make a pointer point to something different (even after it was pointing to the same thing as another pointer), with references, if one reference is updated, then the other references which pointed to the same thing are also updated to point to the very same object.
But then I went on to say that the above use of references is pretty useless (and perhaps this is where I went wrong), because I couldn't see a practical advantage to assigning by reference: since both references end up pointing to the same thing, you could easily do with one reference, and couldn't think of a case where this wouldn't be the case. I went on to explain that references are useful as pass-by-reference function parameters, but not in assignments. But the interviewer said they assign by reference in their code all the time, and flunked me (I then went on to work for a company that this company was a client of, but that's besides the point).
Anyways, several years later, I would like to know where I could have gone wrong.
To begin with, I'd hope for that company's sake that wasn't the ONLY reason they didn't hire you, since it's a petty detail (and no, you don't really know exactly why a company doesn't hire you).
As touched on in the comment, references NEVER change what they refer to within their lifetime. Once set, a reference refers to that same location, until it "dies".
Now, references are quite useful to simplify an expression. Say we have a class or structure with a fair amount of complicated content. Say something like this:
struct A
{
int x, y, z;
};
struct B
{
A arr[100];
};
class C
{
public:
void func();
B* list[20];
};
void C::func()
{
...
if (list[i]->arr[j].x == 4 && list[i]->arr[j].y == 5 &&
(list[i]->arr[j].z < 10 || list[i]->arr[j].z > 90))
{
... do stuff ...
}
}
That's a lot of repeats of list[i]->arr[j]
in there. So we could rewrite it using a reference:
void C::func()
{
...
A &cur = list[i]->arr[j];
if (cur.x == 4 && cur.y == 5 &&
(cur.z < 10 || cur.z > 90))
{
... do stuff ...
}
}
The above code assumes do stuff
is actually mofidying the cur
element in some way, if not, you should probably use const A &cur =...
instead.
I use this technique quite a bit to make it clearer and less repetitive.