DEV Community

Discussion on: C++ References

Collapse
 
dwd profile image
Dave Cridland • Edited

A reference is, of course, a bit of syntactic sugar for a pointer. But there are two differences:

  • You cannot rebind a reference. Assignment to a reference assigns to the referenced lvalue, and not to the reference itself, unlike a pointer:
int one=1, two=2;
int & ref = one;
int * ptr = &two;
std::cout << *ptr << ", " << ref << std::endl; // "2, 1\n"
ptr = one; // Pointer assignment
std::cout << *ptr << ", " << ref << std::endl; // "1, 1\n"
ref = two; // lvalue assignment
std::cout << *ptr << ", " << ref << std::endl; // "2, 2\n"!!

The last line prints two, because the reference is bound to one, and you've just changed the value. The pointer, now also bound to one, therefore prints the same value.

You can make a pointer non-rebindable with a const after the point, though. References, and const-pointers, are similar to the effect of the const keyword in Javascript, and the final keyword in Java.

  • Assignments to and from a reference type are a bit magic. This is best shown with a class type, like a string.
std::string s1 = "Hello world!"; // Legal - s1 is created containing the C-style string's contents.

void f1(std::string); // Always copies.
void f2(std::string &); // Always references existing object.
void f3(std::string const &); // Can reference anything.

Calling any of these functions with s1 is fine - there's always something to reference. f2() might change the string though.

But you cannot call f2 with either an expression, or a literal - because f2 says it might change the string, f2 cannot be called with a temporary.

No such protections exist for pointers.

You can, though, create a nullptr reference quite easily:

int & nullref = *reinterpret_cast<int *>(nullptr);
// Or if you prefer:
int * ptr = nullptr;
int & nullref = *ptr;

Of course, the moment you do anything with ref, you're implicitly referencing it, and you'll experience the joy of undefined behaviour.