Sunday, December 4, 2011

The Trouble with References in C++


References in C++ are essentially pointers that masquerade as values.  They were originally added to the language in order to facilitate operator overloading, so that you could write:

bool operator==(const Foo& lhs, const Foo& rhs);
And then use it sensibly in a program like this:
if(foo_a == foo_b) {}
But consider this line of code:
x = calc_x();
What do you think is happening here?
Now lets say we widen our view a bit:

void Foo::do_something()
{
    int& x = this->m_x;
    // some other code...
    x = calc_x();
}

Suddenly, that same line has very different implications.  We aren't just assigning a value to x; we're mutating the state of the object.
The problem with references in C++ is that appears you are working with values when you are, in reality, using pointers.  This violates the Principal of Least Surprise.  It forces you to read all of the code in a function, before being able to comprehend a single line of it.  

If you rewrite this same routine with pointers instead of references, it becomes immediately clear what is happening:

void Foo::do_something()
 { 
    int* x = &this->m_x; 
    // some other code...     
    *x = calc_x();     
}

It is no wonder then that Google's C++ Style Guide requires that only const references be used.