There are different ways in which parameter data can be passed into and out of methods and functions. It is beyond the scope of these notes to describe all such schemes, so we will consider only the two most common methods used in C++ and Java: "pass by value" and "pass by reference".

First some important terminology:

Definition: Formal Parameter

A variable and its type as they appear in the prototype of the function or method.

Definition: Actual Parameter

The variable or expression corresponding to a formal parameter that appears in the function or method call in the calling environment.


Pass by Value

Using "pass by value", the data associated with the actual parameter is copied into a separate storage location assigned to the formal parameter. Any modifications to the formal parameter variable inside the called function or method affect only this separate storage location and will therefore not be reflected in the actual parameter in the calling environment. For example (this could be either C++ or Java):

void cribellum(int x) // Formal parameter is "x" and is passed by value.
{
	x = 27;
}

void someCaller()
{
	int y = 33;
	cribellum(y); // Actual parameter is "y"
	// Actual parameter "y" still has 33 at this point.
	...
}

Pass by Reference

Using "pass by reference", the formal parameter receives a reference (or pointer) to the actual data in the calling environment, hence any changes to the formal parameter are reflected in the actual parameter in the calling environment. Here is a modified version of this example (now strictly a C++ example since Java does not allow primitive types to be passed by reference):

void cribellum(int& x) // Formal parameter "x" is now passed by reference.
{
	x = 27;
}

void someCaller()
{
	int y = 33;
	cribellum(y);
	// Actual parameter "y" now has 27 at this point.
	...
}

Using expressions as actual parameters

When the formal parameter is passed by value, the actual parameter can be an expression. However, when the formal parameter is passed by reference, the actual parameter must refer to one specific instance of the formal parameter type stored in programmer-accessible memory. The following table illustrates valid and invalid examples.

Assume the following variables are defined in the calling environment:

int i = 3, y = 33;

Assume further that values is an array of length 10 of integers.

Language:
prototype
     →
call
Java:
void cribellum(int x)
C++:
void cribellum(int x)
C++:
void cribellum(int& x)
cribellum(2*y);OKOKcompilation error
cribellum(14*y + i - 10);OKOKcompilation error
cribellum(3);OKOKcompilation error
cribellum(y);OKOKOK
cribellum(values[2]);OKOKOK
cribellum(values[3*i - 2]);OKOKOK

How do Java and C++ Compare?

Java only supports "pass by value" for primitive types, and it only supports "pass by reference" for object types (including arrays since they are objects in Java). This is why you never see type modifiers like "&" on formal parameters in Java – it only supports one way to pass parameters.

C++ supports both "pass by value" and "pass by reference" for both primitive types and object types. Hence it requires use of "&" so that the programmer can specify which of the two is desired for a given parameter.

What about arrays? In C++, conventional arrays are not objects. (Recall the comments in the earlier Arrays section.) Conventional C++ arrays can only be passed by reference, in large part due to the fact that their size is unknowable to the C++ runtime system, hence it would be impossible to make a local copy for a "pass by value" scheme. From a syntactical point of view, the "&" modifier is not used for formal parameter arrays in C++ since they can only be passed by reference.

However:

Recall, too, from the earlier Arrays section that there are STL classes that are array-like (e.g., std::array and std::vector). Pass by value is supported for these classes.

Finally:

You may also hear "pass by address" – both in the context of how conventional arrays are passed as well as how other primitive and object types can be passed – but there are subtleties involved that we will postpone until later. For now, just bear in mind that "pass by address" does not really represent a parameter passing scheme that is any different from those discussed here. (It turns out it is really just a specific instance of pass by value.) In any event, we will revisit this when we discuss C++ pointer variables in the Basic Pointer Use section later.