- Learn C++ Test Site - https://test.learncpp.com -

10.2 — In and out parameters

Parameters passed by value, const reference, or pointer to const are sometimes called in parameters (short for input parameters) because such parameters are used to send values into the function (the function uses those values as inputs).

However, parameters passed by non-const reference allow a function to modify the value of the argument. If a function modifies the value of an argument, it is, in effect, outputting a value.

In-out parameters (short for input and output parameters) are parameters where the function both uses and changes the value of the parameter. The addOne function we showed in a prior example has an in-out parameter:

Out parameters (short for output parameters) are parameters that the function only uses for outputting value. Out parameters are sometimes labeled with an “out” or “Out” prefix or suffix to indicate their output-oriented nature. This can help remind the caller that the initial value passed to these parameters will be overwritten. By convention, out parameters are typically the rightmost parameters.

Here’s an example of a program that uses output parameters:

This function takes one parameter (by value) as input, and “returns” two parameters (by reference) as output.

This is one way for a function to return more than one value.

The downsides using references for out and in-out parameters

While out and in-out parameters might seem like a convenient way to return multiple values, they have a few downsides. First, the caller must pass in arguments to hold the outputs even if the caller doesn’t intend to use them. More importantly, the syntax is a bit unnatural, with both the input and output parameters being mixed together in the function call.

This can make it easy to overlook that some arguments might be modified.

Some programmers and companies frown upon using non-const references for out and in-out parameters because the calling syntax offers no clue that the function will change the value. For example:

And we blew up the world again! We really need to kick this habit.

Note that there’s no easy way to tell by scanning the function calls that mode is an in parameter for function doSomething and an in-out parameter for function doSomethingElse. They look identical. This makes out and in-out parameters passed by non-const reference potentially dangerous, because a value could be changed without the programmer realizing that was possible.

For advanced readers

This syntax issue can be addressed by using pass by address (using pointers) instead.

Instead of using an in-out parameter, it’s better to have an in-parameter and return the modified value using the function’s return value:

This makes it clearer that value is being modified.

Although out parameters offer one way for a function to return multiple values, this use is generally frowned-upon, as there are better ways to return multiple values (e.g. structured binding).

Best practice

Avoid out parameters (use other methods to return multiple values), and avoid in-out parameters when practical.

Pass by address helps makes modifiable parameters explicit

In lesson The C++ Tutorial (Test Site) [1] we talked about how using references for in-out parameters can lead to problems recognizing that a function call may modify a value passed in:

Because of this, some companies (such as Google) have guidelines that state in-out parameters should be passed by address rather than by reference. Let’s update the program above to use pass by address:

Passing by address requires the caller to pass in a normal variable argument using the address-of operator (&), which helps identify that the function could modify the argument just by looking at function call.

This has a few downsides: first, the function now has to deal with null pointers, which means we’ve traded an unlikely problem (the function modifying a value without the programmer realizing it) for possible program crashes or asserts. Second, it doesn’t work for pointers, which don’t need the explicit ampersand to be passed by address, and still allow modification of the value being pointed to.

Given this, our recommendation is to hold the course on preferring pass by reference for in-out parameters.