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.
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.
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
.
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}
sc-1-7: What is the output from this program?
More to Explore