3.2. Passing parametersΒΆ

In C and C++, parameter passing defaults to pass by value. Unless you specify otherwise, function parameters are initialized with copies of the actual arguments, and function callers get back a copy of the value returned by the function. Pass by value is the simplest way to get data into and out of functions.

void printFavorite(int x) {
  // 'x' is a copy of 'favorite'
  std::cout << "my favorite number is " << x << '\n';
}

int main() {
  int favorite = 72;
  printFavorite(favorite);
}

The important point is that two copies of my favorite number are stored. The one declared in main, favorite, and the one declared in printFavorite, x. The parameter x is initialized using the value of favorite in main.

Activity: CodeLens 3.2.1 (function_parameter_pass_cl1)

More than one parameter can be passed. For example, a function to add two numbers makes copies of both parameters adds them together and returns a result, which is also copied.

Step through this example and see how the copies of both local variables and return values are managed on the stack.

Activity: CodeLens 3.2.2 (function_parameter_pass_cl2)

One benefit of pass by value is that local changes to parameters do not impact the caller. That is, the caller can trust their data has not been modified.

For large / complex data types, however, pass by value becomes expensive even in small programs. An alternative to pass by value, is called pass by reference. The function parameter passed into the function is still a new variable. That does not change. However, rather than passing a copy of the entire object, instead we bind the address of the original object to a new variable. Only the object reference is passed to the function.

In this respect, a reference behaves much like a const pointer.

  • Both require an initial value in order to compile

  • Neither can refer to (or point to) a different object

int  n = 3;          // typical int declaration
int  m = 5;

int& a = n;          // a refers to n
int* p = &n;         // p points to n,
                     // but could point to something else

int* const p2 = &m;  // p2 point to m and can only point there

The following are compile errors:

int& b;              // a reference that doesn't refer to anything
p2 = &n;             // attempt to change what a const pointer points to

If the pointer comparison is confusing, do not worry. We will delve more deeply into pointers soon, this is just for comparison for those people who have an introduction into pointers.

We use the address of operator & to declare that only the address of the variable is passed, rather than a copy. The primary advantage is that since all addresses are the same size, the cost of passing is the same, regardless of how large the object is.

Understanding references is critical to understanding how C++11 and later version of the language function. References are a major new language feature and we will be using them often from now on.

Try This!

Modify the print_n function signature so that the variable repeat is a reference instead of a copy.

A common source of confusion when starting out with references is keeping the operator& straight.

The meaning of this operator depends on how it is used.

On the left-hand side of an assignment, or in function parameters, & always defines a reference to a type:

int& a = 3;
const int& cr(a);     // cr refers to a,
                      // but we can't change the value of a using cr

void show_usage (std::string& message);

const double& pi = 3.1415926;

On the right-hand side of an assignment, & almost always means address of a variable. The only exception is when casting to a reference type:

int n = 3;
int* p = &n;      // p points to the address of the variable n

const int& cr(a);     // const reference

// cast away the 'const' part of cr
int& r2 = const_cast<int&>(cr);

In the last code block, notice that both cr and r2 refer to a, however, r2 can change the value of a because we cast away the const modifier that was part of cr.

Although the language allows casting away const like this, you should use this feature very sparingly.

There is a lot going on in the following program. You should step through this code and make sure you understand what is happening to the variables in main and the functions called from main.

Activity: CodeLens 3.2.6 (function_parameter_pass_by_ref_cl)

Given the following program:

 1#include <iostream>
 2
 3int change_and_add(int &a, int &b) {
 4  a = 3;
 5  b = 4;
 6  return a + b;
 7}
 8
 9int main() {
10  int a = 1;
11  int b = 2;
12  int c = change_and_add(a, a);
13  std::cout << a << b << c;
14}

You have attempted of activities on this page