Gaurav
Gaurav

Reputation: 1600

Clarification regarding passing arguments by reference

While reading about passing references to function as parameters, I found this article passing arguments by reference (and the code it talks about) which says at a point that:

void getSinCos(double degrees, double &sinOut, double &cosOut)
{
   //SOME PROCESSING WITH THE PARAMETERS
}

The caller must pass in arguments to hold the updated outputs even if it doesn’t intend to use them. More importantly, the syntax is a bit unnatural, with both the input and output parameters being put together in the function call. It’s not obvious from the caller’s end that sin and cos are out parameters and will be changed. This is probably the most dangerous part of this method (as it can lead to mistakes being made). Some programmers and companies feel this is a big enough problem to advise not passing by reference this way, and using pass by address instead when mixing in and out parameters (which has a clearer syntax indicating whether a parameter is modifiable or not).

Sure we can't pass temporaries like argument 3 or some other integral/double literal when the parameters defined is a non-const reference but how can the modification of the input variable and restoring of the output in the same variable (as the changes are made to the original variable) be troublesome as this article points out? Can somebody please guide me as I am new to C++.

Upvotes: 2

Views: 74

Answers (2)

user7860670
user7860670

Reputation: 37587

That article does not say anything about "the modification of the input variable and restoring of the output in the same variable" it only says that it is not obvious which arguments can be changed by the function call:

int x{};
int y{};
foo(x, y); // can you guess which variable has changed?

The part about pass by address having a "clearer syntax indicating whether a parameter is modifiable or not" is complete bullshit though. Not only it suffers from the same problem as pass by reference, but it also implies that some arguments can be optional and possible ownership transfer

int x{};
int y{};
foo(&x, &y); // can you guess which variable has changed?
foo(nullptr, &y); // can you guess whether this is correct usage?
foo(&x, &y); // can you be sure that foo won't delete pointer to x?

To be on the safe side one can use something like explicit pass by (const) reference:

int x{};
int y{};
foo(::std::as_const(x), y); // alright, x should not be changed inside

Upvotes: 3

Blaze
Blaze

Reputation: 16876

It's something that people simply may not expect. Suppose you have this code:

int x = 5;
foobar(x);

What is the value of x after the function call? Most people would expect it to still be 5, because barring undefined behavior, it can't change when passed by value. In C there isn't even pass by reference, so the value would always be 5. Now in C++, there suddenly is passing by reference, and just from that snippet of code, you have no way of knowing whether x will change after the function call. You'd have to look at the actual signature of foobar for that.

It's not "dangerous" on its own, but if used poorly, it may lead to unclear and misleading code. Especially if you have a mix of parameters, some being out parameters, some not, and some having misleading names. In your example, the parameter names contain out to indicate that they're out parameters, and that's good style that mitigates this danger.

Contrast this with following snippet from here explaining pass by reference how it is in C#:

void Method(ref int refArgument)
{
    refArgument = refArgument + 44;
}

int number = 1;
Method(ref number);
Console.WriteLine(number);
// Output: 45

Here you instantly see that it's passed by reference because it says ref number.

Upvotes: 4

Related Questions