More on References

Here’s some more stuff on references. As Mike Dunn commented on the previous blog entry, a reference cannot be re-referenced (for lack of a better word) to a different object. So if you have a reference, then it will always be an alias for the very same object it was an alias for when it got created. This is similar to a const pointer, but pointers and references are not the same thing at all – so don’t go about thinking that a reference is a const pointer.

You can also use references as function returns, including class member function returns. See the following code snippet :-

int Func1(...)
{
  //...
}

int& Func2(...)
{
  //...
}

//...

int i = Func1(...);

int j = Func2(...);

When Func1 is called, the return value is passed by value, which means a new temporary value is created to which the return value is copied to and then again copied to the variable i. But when Func2 is called, the temporary value is not created though the second copying is still done – but that is part of program logic and not to do with the functions. Obviously this has more value in terms of efficiency when you are returning a large object, rather than a simple native type as you are in the above example. But then, when you are returning a reference, you have to be very very careful that you do not return a temporary automatic variable with scope only within the function, else you will have disastrous results. Because now the reference is an alias for an object that does not exist anymore.

Using references as return values has a remarkable side-effect – the function return is now an l-value. See the following code snippet :-

class A
{
public:
  A(int y):m(y){}
  A(const A&)
  {
    printf("*** copy ctor ***\r\n");
  }
  int& Num()
  {
    return m;
  }
private:
  int m;
};

A g_A(5);

A& GetA()
{
  return g_A;
}

int _tmain(int argc, _TCHAR* argv[])
{
  int x = GetA().Num(); //l-value usage
  printf("%d\r\n",x);

  A a(100);
  int i = a.Num() = 99; //l-value usage
  printf("%d\r\n",i);
  printf("%d\r\n",a.Num());

  return 0;
}

You can see how I’ve been able to use syntax like GetA().Num() and a.Num() = 99. We can actually write fancy looking code (which saves us some typing) such as :-

class A
{
public:
  A():m(0){}
  A& Add1()
  {
    m++;
    return *this;
  }
  A& Mul7()
  {
    m *= 7;
    return *this;
  }
  A& SquareNum()
  {
    m *= m;
    return *this;
  }
  void Show()
  {
    cout << m << endl;
  }
private:
  int m;
};

int _tmain(int argc, _TCHAR* argv[])
{
  A a;
  a.Add1().Mul7().SquareNum();
  a.Show();
  return 0;
}

a.Add1().Mul7().SquareNum() is actually a shorter form of a.Add1(); a.Mul7(); a.SquareNum(). Those of you who’ve used MFC might remember how CListView::GetListCtrl actually returns a CListCtrl& which lets you write code like GetListCtrl().InsertColumn(...) which is sorta easy on the eyes.

Advertisements
Posted in C++

2 thoughts on “More on References

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