A function and its caller communicate with each other via two mechanisms: parameters and return values. When a function is called, the caller provides arguments, which the function receives via its parameters.
In Parameters
In most cases, a function parameter is used only to receive an input from the caller. Parameters that are used only for receiving input from the caller are sometimes called in parameters.
#include <iostream>
void print(int x) // x is an in parameter
{
std::cout << x << '\n';
}
void print(const std::string& s) // s is an in parameter
{
std::cout << s << '\n';
}
int main()
{
print(5);
std::string s { "Hello, world!" };
print(s);
return 0;
}
In-parameters are typically passed by value or by const reference.
Out Parameters
A function argument passed by (non-const) reference (or by address) allows the function to modify the value of an object passed as an argument. This provides a way for a function to return data back to the caller in cases where using a return value is not sufficient for some reason.
A function parameter that is used only for the purpose of returning information back to the caller is called an out parameter.
For example:
#include <cmath> // for std::sin() and std::cos()
#include <iostream>
// sinOut and cosOut are out parameters
void getSinCos(double degrees, double& sinOut, double& cosOut)
{
// sin() and cos() take radians, not degrees, so we need to convert
constexpr double pi { 3.14159265358979323846 }; // the value of pi
double radians = degrees * pi / 180.0;
sinOut = std::sin(radians);
cosOut = std::cos(radians);
}
int main()
{
double sin { 0.0 };
double cos { 0.0 };
double degrees{};
std::cout << "Enter the number of degrees: ";
std::cin >> degrees;
// getSinCos will return the sin and cos in variables sin and cos
getSinCos(degrees, sin, cos);
std::cout << "The sin is " << sin << '\n';
std::cout << "The cos is " << cos << '\n';
return 0;
}
The function has one parameter degrees
(whose argument is passed by value) as input, and returns two parameters (by reference) as output.
We have named these out parameters with the suffix “out” to denote that they are out parameters. This helps remind the the caller that the initial value passed to these parameters doesn't matter, and that we should expect them to be overwritten. By convention, output parameters are typically the rightmost parameters.
Let's explore how this works in more detail. First the main function creates local variables sin
and cos
. Those are passed into function getSinCos()
by reference (rather than by value). This means function getSinCos()
has access to the actual sin
and cos
variables in main()
, not just copies. getSinCos()
accordingly assigns new values to sin
and cos
(through references sinOut
and cosOut
respectively), which overwrites the old values in sin
and cos
. Function main()
then prints these updated values.
If sin
and cos
had been passed by value instead of reference, getSinCos()
would have changed copies of sin
and cos
, leading to any changes being discarded at the end of the function. But because sin
and cos
were passed by reference, any changes made to sin
or cos
(through references) are persisted beyond the function. We can therefore use this mechanism to return values back to the caller.