References Versus Pointers

Summary

In this post, I will discuss when to use References and when to use Pointers in C++.

Conclusion

As usual, I present the conclusion first.
1. If the varible can be nullptr, declare the varible as a pointer;
2. If the you want to re-assign the varible, declare the varible as a pointer;
3. Otherwise, use references.

Details

I come across this question when learning the compiler course. Pointers make things complicated when designing compilers in C. And in C++ it becomes more complex after references are introduced.

Why C++ use pointers?

  1. For compatibility issue, we know pointers are inherited from C.
  2. In some situations (see the above conclusion), pointers are irreplaceable.

Why introduce references?

Direct reason that references were introduced in C++ is to support operator overloading.

void f1(const complex* x, const complex* y) // without references {
        complex z = *x+*y;  // ugly
        // ...
}
void f2(const complex& x, const complex& y) // with references {
        complex z = x+y;    // better
        // ...
}   

Can referent be a nullptr?

No. Although some compilers will not report it. It’s still illegal. “The C++ language, as defined by the C++ standard, says it’s illegal.”

Foo &foo_ref = *foo_pointer;
cout << foo_ref.bar << endl; // Process finished with exit code 11

How to reset a reference variable to another referent?

No way. Once a reference is bound to an referent, it can not be “reseated” to another referent. The reference isn’t a separate object and the reference is its referent. In that sense, a reference is similar to a const pointer such as int* const p (as opposed to a pointer to const such as const int* p).

See the following example to fully understand it.

class Foo {
public:
    int bar;
    explicit Foo(int x){
        bar = x;
    };
};
int main() {
    Foo foo1(1);
    Foo foo2(2);
    Foo &foo_ref = foo1;
    cout << foo1.bar << endl;     //1
    cout << foo2.bar << endl;     //2
    cout << foo_ref.bar << endl;  //1
    foo_ref = foo2;               //Actually foo1 is a new copy of foo2 now
    cout << foo1.bar << endl;     //2
    cout << foo2.bar << endl;     //2
    cout << foo_ref.bar << endl;  //2
}

Reference

ioscpp.org

Leave a Reply

Your email address will not be published. Required fields are marked *