Lab 8: Experiment 6

Constant Reference Parameters

We've declared constants to store constant information simply by inserting the keyword const in front of their declarations. But can we also do this with parameters? After we answer this question, we'll see why we would even want to do this.

Issue: Can we declare a reference parameter to be constant? If so, can we change its value?

Hypothesis: We can declare a constant reference parameter, but we cannot change its value.

Experiment: We can test our hypothesis by making one of the parameters in change() a constant reference parameter. Such a change must be made in both the prototype

    void change(int & param1, int param2, const int & param3);
and in the definition:
void change(int & param1, int param2, const int & param3)
{
  param1 = 1;
  param2 = 2;
  param3 = 3;
}
This is a simple change to make after the previous experiment.

Observation: Compile and execute your program.

Question #8.6.1: Can you compile the program? If not, what error message do you get? If you can, what is displayed by the program?

Conclusions:

Question #8.6.2: Is our hypothesis correct? How do you know? If it's not correct, what should it be?

Note 1: There are two parts to our hypothesis. First, can you declare a constant reference parameter? Second, can you change its value? The answers to these may not be the same.

Note 2: Observing carefully where the compiler complains about your code can help with finding what causes an error.


So why bother with constant reference parameters? Why not just use value parameters?

The answer has to do with efficiency. Suppose we have a program like that in Lab 6 that repeatedly calls a string-processing function, sending it one or more strings, and the function receives these via value parameters. With each call to such a function, a copy of each argument must be made and assigned to the corresponding parameter. For primitive types (e.g., int, double, bool, char, etc.), such copying takes vary little time. But this is not true for objects whose type is string or some other class. An object of type string, for example, consists not merely of the characters that make up the string that must be copied but also code for all of its built-in functions — e.g., size(), substr(),find(), [], +, and many other built-in operations (see Lab 6).

Copying such objects to value parameters with each function call takes time and the performance of the program can seriously degrade. Using a reference parameter eliminates this excessive copying because only a reference to the object —i.e.,the location in memory where its code is stored — needs to be sent to the function. However, this is not enough in itself, because the function could still modify such objects. And that's where constant reference parameters come to the rescue — the arguments need not be copied and they are protected from being modified.

We've been discussing string objects, but the preceding discussion also applies to other complicated objects — e.g., objects whose types are other classes as well as arrays, vectors, files, and other structures provided in C++ or that are created by the programmer.

A rule of thumb: Pass primitive type values (e.g., int, double, bool, char, etc.) by value unless the function has to change their values; other type objects — especially if you have to load a library to use them — should be passed by reference or constant reference.


Back to the Lab Exercise


Report errors to Larry Nyhoff (nyhl@cs.calvin.edu)