C++ References

These days, I spend most of my free time trying to understand the C++/CLI language and syntax, and very often I have to refresh my native C++ knowledge. So, expect some basic C++ stuff during the next few weeks, and if you are an experienced C++ coder, then please skip these entries rather than going through then and then feeling annoyed at having read something you knew for years. These entries are meant for relatively inexperienced C++ developers 🙂

In C++, a reference is an alias for a variable – C did not have the concept of a reference. You specify that a variable is a reference type by adding an & to the right of the typename.

  • int i = count; Here, i is a normal variable and the value of count is copied to i. Changing the value of count will have no effect on i.
  • int& j = count; Here j is a reference which is an alias for count. Changing the value of count is equivalent to changing the value of j and vice-versa.

References are a lot more efficient as function arguments than pass-by-value arguments, because in the latter case, a new temporary copy of the passed object has to be created. See the following code snippet :-

class A
{
public:
  A(){}
  A(const A&)
  {
    cout << "A::copy_ctor" << endl;
  }
};

void Func1(A a)
{
  cout << "In Func1" << endl;
}

void Func2(A& a)
{
  cout << "In Func2" << endl;
}

int _tmain(int argc, _TCHAR* argv[])
{
  A a;
  cout << "Calling Func1" << endl;
  Func1(a);
  cout << "Calling Func2" << endl;
  Func2(a);

  return 0;
}

/* Output :-

	Calling Func1
	A::copy_ctor
	In Func1
	Calling Func2
	In Func2

*/

As you can see, calling Func1 results in the copy constructor of the class A being invoked, whereas calling Func2 does not make a copy as it expects a reference as argument. In cases where the object passed is large and where the creation of a copy is time-consuming or memory-wasting, references do provide a more elegant and efficient option. Of course you could use a pointer type and modify the prototype of the function to void Func(A* pA) but now you would have to check for a null pointer, and the caller might often have to do something like A a; Func(&a); which is not very aesthetic looking.

BTW, you have to be wary of something if you have a C background. Take a look at the following code :-

void DoStuff(A& a)
{
  a.m = 10; //modify a
}

int _tmain(int argc, _TCHAR* argv[])
{
  A a;
  DoStuff(a);

  //...

Now in C, you’d expect that DoStuff(a) won’t modify a as a is expected to be passed by value. In C++, this depends on whether DoStuff takes a reference or a normal variable. But then again, the solution is very straightforward, all you need to do is change the function prototype to take a reference to a const:-

void DoStuff(const A& a)
{
  a.m = 10; //Won't compile - C2166
}

Now, you won’t be able to inadvertently corrupt an object that you pass to the function. There’s lot more to talk about on references, but I’ll probably do them in a future entry.

Advertisements
Posted in C++

4 thoughts on “C++ References

  1. “References are a lot more efficient as function arguments than pass-by-value arguments, because in the latter case, a new temporary copy of the passed object has to be created.”

    Only if an object has a non-trivial copy constructor and is over a certain size. I’ve been able to pass 24byte structs by value faster than passing a reference to it because in the former case there would be an extra indirection rather than accessing it directly from the stack’s base ptr. Plus the optimizer can figure out pointers can’t alias it if you pass it by value as opposed to generating more careful code.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s