References, parameter passing, returns

L-Values and R-Values

Recall that there is a difference between the concept of an Lvalue and an Rvalue. These get their names from the types of items that can go on the left-hand-side and right-hand-side of an assignment statement. Examples:
   int x, y;			// L-values
   int list[10];		// L-value
   list[5] = 20;		// list[5] is an L-value (a storage location in the named array)
   int z = x + y;		// x + y is an R-value.  z is an L-value
   string str = "Hello";	// str is L-value.  "Hello" is R-value

   // Assume Fraction is a class
   Fraction f;			// L-value
   Fraction g(1,2);		// L-value
   g = Fraction(3,4);		// this direct constructor call creates an R-value
				//  which is assigned into g with assignment operator
L-values can be used in R-value positions, when we are just accessing the stored value.
   x = y;			// y is L-value, but can be used in R-value position

Lvalue References

The standard reference variable you've learned about previously is now referred to in the C++11 standard as an Lvalue reference. The following notes page from Programming 1 illustrates the usual use of this type of reference variable: The most important use of reference variables is in parameter passing. Most notably the choices between: The usual decision factors for choosing how to pass parameters are:
  1. Do we want the formal parameter to be able to change the original argument? If yes, choose pass by reference
  2. Otherwise, is this a small object with little copy overhead? (If so, pass by value is fine).
    Or is this a large object with large or complex copy overhead? (If so, best to use pass by const reference)

Other uses for L-value references

Remember that a reference variable acts as a nickname, or synonym, for the object it references. This comes in handy in a few other places besides parameter passing

Aliasing complex names

Use in range-based for loops

Avoiding unnecssary copies


Return-by-value vs Return-by-reference

Note that function returns have the same options as the parameter passing list: However, be very careful when returning a reference! Make sure you are returning something that will still live past the function's execution! See these two sample functions:
  // WHICH of these two functions is a GOOD definition?
  // and WHICH of these uses a reference return badly?

  const string & findMax(const vector<string> & list)
  {
     int maxIndex = 0;
     for (int i = 1; i < list.size(); i++)
        if ( list[maxIndex] < list[i])
           maxIndex = i;

     return list[maxIndex];
  }

  const string & findMax(const vector<string> & list)
  {
     string maxValue = list[0];
     for (int i = 1; i < list.size(); i++)
        if (maxValue < list[i])
            maxValue = list[i];
 
     return maxValue;
  }

R-value references

c++11 introduced a new kind of reference variable -- an r-value reference

R-value references as parameters

Why? What's the point?!

Well, I'm glad you asked... :-)

Move copy constructor and assignment operator

Here is an example to help demonstrate the move copy constructor and move assignment operator. This is the start of a simple non-templated vector class that stores a list of integers.

The protypes of the big five for this class:
   ~IntVector();				// destructor
   IntVector(const IntVector& rhs);		// copy constructor
   IntVector(IntVector&& rhs);			// move constructor
   IntVector& operator=(const IntVector& rhs);	// copy assignment operator
   IntVector& operator=(IntVector&& rhs);	// move assignment operator