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.