DEV Community

C++ References

Noah11012 on February 05, 2019

C++ is backward compatible with C so it inherited pointers. A quick recap if you don't know what a pointer is: a pointer is a variable that holds t...
Collapse
 
vberlier profile image
Valentin Berlier

I don't write a lot of C++ but shouldn't your code example declare some_value as a reference to int to match the return type of the return_five function?

int &some_value = return_five();
Collapse
 
noah11012 profile image
Noah11012

No, because the non-reference variable will contain the value of the bounded value of the reference.

int value = 100;
int &ref_value = value;
int new_value = ref_value;

std::cout << new_value << "\n"

Output:

100
Collapse
 
vberlier profile image
Valentin Berlier

Oh yeah okay you're dereferencing when assigning to some_value, gotcha. Just another question: if you use auto, what would the inferred type be?

int value = 100;
int &ref_value = value;
auto new_value = ref_value;

Does new_value remain a reference or now contains the dereferenced value?

Thread Thread
 
noah11012 profile image
Noah11012

Not entirely sure as auto in some instances is tricky. I believe in your example that new_value will the type int.

Thread Thread
 
dwd profile image
Dave Cridland

It will be int&, I think: en.cppreference.com/w/cpp/language...

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.