In C++ Output Parameter vs Return Value - c++

What is/are the difference(s) between output parameters and return values? I've looked everywhere and I can't seem to find a simple definition for either.

The return value is something well defined in C++; for instance, x in return x; is the return value, whereas int in the function declaration int myfunc() is the return type.
The concpet of output paramters is not defined in C++. However someone would interpret it as either of the following:
function parameters passed by non-const reference, as long as you actually modify it in the function, otherwise why would you call it output? An example is x in the following function declaration: void myfunc(int& x);
function parameters passed by (not necessarily const) pointer to non-const, like x in both the following function declarations: void fun1(int * x) and void fun2(int * const x);
concerning this latter case, it allows "encoding" a missing parameter in as a nullptr default value, as in void fun3(int * x = nullptr).
A first difference is aesthetic: which one you like the most?
Another one is that the former concept and syntax help you convey the message that the function is giving back a value, something which is clear at the call site too (whereas at the call site you might not know if a parameter corresponding to an argument is passed by reference or not).
There are several differences between this two ways a function can have "consequences" at the caller site. For instance, you can only have one return value, whereas you can have as many paramters as you like.
Performancewise, complier optimizations can minimize the difference in performance, and maybe you should not worry (yet) about it.

Related

About to pass a reference as an argument in a function to alter the value of the argument variable.

I was reading "Beginning C++ Through Game Programming, Fourth Edition" when I found a section about to pass a reference as an argument in a function that says:
"Pass a reference only when you want to alter the value
of the argument variable. However, you should try to avoid changing
argument variables whenever possible."
Basically it says that I shoud avoid to do something like this:
void swap(int& x, int& y)
{
int temp = x;
x = y;
y = temp;
}
But, why should I avoid doing this?
I found very useful to create functions to change variables, because these functions keep my code organized avoiding me to write every variable change in the main() function, and they also avoid me to write the same code repeatedly.
What alternative is there if I should not do this?
With the case of swap, pass by reference shoud be used, because multiple variables are being changed in the function and the expected behavior of the function is obvious. If you were only changing one variable or have a function that should be returning a result, then it is better to return a value for the most part (With some exceptions). For example, supoose you had a function sum():
int sum(int a, int b)
{
return a + b;
}
Usage of this function might be:
int x = sum(1, 2); // Obvious and to the point
Since there is no need to change any of the variables, one would use pass by value here (Pass by const reference doesn't matter here, since POD types are pretty small). If you used pass by reference here, then the function would have changed to:
void sum(int a, int b, int& sum)
{
sum = a + b;
}
Usage of the function above might be:
int s;
sum(1, 2, s); // Obscure, unclear
Disadvantages of this are that it is unclear what the intent of the function is, and now the result of the function cannot be passed to another function in one line. So pass by reference should only be used when absolutely necessary.
On a side note, using a const reference for passing large objects to functions is always recommended, since it avoids a copy.

Google's style guide about input/output parameters as pointers

The Google C++ Style Guide draws a clear distinction (strictly followed by cpplint.py) between input parameters(→ const ref, value) and input-output or output parameters (→ non const pointers) :
Parameters to C/C++ functions are either input to the function, output
from the function, or both. Input parameters are usually values or
const references, while output and input/output parameters will be
non-const pointers.
And further :
In fact it is a very strong convention in Google code that input arguments are values or const references while output arguments are pointers.
But I can't figure out why input/output arguments (I leave output arguments aside) should not be passed by reference. On stackoverflow there are plenty of topics related to this question : e.g. here, the accepted answer clearly say that
it's mostly about style
but that if
you want to be able to pass null, you must use a pointer
So, what's the point to always demand a pointer if I want to avoid the pointer to be null ? Why only use references for input arguments ?
The reason for demanding that output parameters are passed as pointers is simple:
It makes it clear at the call site that the argument is potentially going to be mutated:
foo(x, y); // x and y won't be mutated
bar(x, &y); // y may be mutated
When a code base evolves and undergoes incremental changes that are reviewed by people who may not know the entire context all the time, it is important to be able to understand the context and impact of a change as quickly as possible. So with this style rule, it is immediately clear whether a change introduces a mutation.
The point they are making (which I disagree with) is that say I have some function
void foo(int a, Bar* b);
If the b argument is optional, or it is unnecessary sometimes, you can call the function like so
foo(5, nullptr);
If the function was declared as
void foo(int a, Bar& b);
Then there is no way to not pass in a Bar.
This point (emphasis mine) is completely opinion-based and up to the developer's discretion.
In fact it is a very strong convention in Google code that input arguments are values or const references while output arguments are pointers.
If I intend for b to be an output parameter, either of the following are perfectly valid and reasonable.
void foo(int a, Bar* b); // The version Google suggests
void foo(int a, Bar& b); // Reference version, also perfectly fine.
You're first question: "So, what's the point to always demand a pointer if I want to avoid the pointer to be null?"
Using a pointer announces to the caller that their variable may be modified. If I am calling foo(bar), is bar going to be modified? If I am calling foo(&bar) it's clear that the value of bar may be modified.
There are many examples of functions which take in a null indicating an optional output parameter (off the top of my head time is a good example.)
Your second question: "Why only use references for input arguments?"
Working with a reference parameter is easier than working with a pointer argument.
int foo(const int* input){
int return = *input;
while(*input < 100){
return *= *input;
(*input)++;
}
}
This code rewritten with a reference looks like:
int foo(const int& input){
int return = input;
while(input < 100){
return *= input;
input++;
}
}
You can see that using a const int& input simplifies the code.
They likely use it for consistency because they use output parameters both as references to existing memory (they're modifying previously initialized variables) and as actual outputs (the output arguments are assumed to be assigned by the function itself). For consistency, they use it as a way to more clearly indicate inputs vs. outputs.
If you never need a function/method to assign the memory of the output parameter, like returning a pointer from a lookup or allocating memory itself and returning it through a pointer, use references. If you need to do that but don't care about using pointers to act as an indication of whether a parameter is input or output, use references for output parameters when appropriate. There's no absolute requirement to use pointers in all cases unless the requirements of that function/method itself requires it.

How to define two functions with the same name and parameters, if one of them has a reference?

I have code:
int SomeClass::sum(int x)
{
return x+=x;
}
int SomeClass::sum(int & x)
{
return x+=x;
}
....
int num = 0;
int result = sum(num);
that not work. How I can use both functions and indicate which of them I want to use when I сall them?
You can provide two different overloads taking int& and const int&, which might somehow meet your needs...
But the whole code is a bit strange... in the function that takes the argument by value you are modifying it (+=), when it probably makes sense to only read it return x+x;. In the overload that takes the reference, you are both modifying the argument and returning the new value. That is a bit strange.
Other than that, sum is a horrible name for a function that multiplies by 2.
You can not have such functions in C++. They will have to be named differently for instance sumByCopy and sumByRef. How would you expect the compiler to decide which one are you referring to at each point?
You can overload in this way, it will compile OK if you do not call any of them directly. However, it will cause ambiguity when you call sum(num). Therefore, it is no sense to provide those overloads of a function since we cannot directly call none of them. This kind of overloads is useless and violates good practice.

If void() does not return a value, why do we use it?

void f() means that f returns nothing. If void returns nothing, then why we use it? What is the main purpose of void?
When C was invented the convention was that, if you didn't specify the return type, the compiler automatically inferred that you wanted to return an int (and the same holds for parameters).
But often you write functions that do stuff and don't need to return anything (think e.g. about a function that just prints something on the screen); for this reason, it was decided that, to specify that you don't want to return anything at all, you have to use the void keyword as "return type".
Keep in mind that void serves also other purposes; in particular:
if you specify it as the list of parameters to a functions, it means that the function takes no parameters; this was needed in C, because a function declaration without parameters meant to the compiler that the parameter list was simply left unspecified. In C++ this is no longer needed, since an empty parameters list means that no parameter is allowed for the function;
void also has an important role in pointers; void * (and its variations) means "pointer to something left unspecified". This is useful if you have to write functions that must store/pass pointers around without actually using them (only at the end, to actually use the pointer, a cast to the appropriate type is needed).
also, a cast to (void) is often used to mark a value as deliberately unused, suppressing compiler warnings.
int somefunction(int a, int b, int c)
{
(void)c; // c is reserved for future usage, kill the "unused parameter" warning
return a+b;
}
This question has to do with the history of the language: C++ borrowed from C, and C used to implicitly type everything untyped as int (as it turned out, it was a horrible idea). This included functions that were intended as procedures (recall that the difference between functions and procedures is that function invocations are expressions, while procedure invocations are statements). If I recall it correctly from reading the early C books, programmers used to patch this shortcoming with a #define:
#define void int
This convention has later been adopted in the C standard, and the void keyword has been introduced to denote functions that are intended as procedures. This was very helpful, because the compiler could now check if your code is using a return value from a function that wasn't intended to return anything, and to warn you about functions that should return but let the control run off the end instead.
In imperative programming languages such as C, C++, Java, etc., functions and methods of type void are used for their side effects. They do not produce a meaningful value to return, but they influence the program state in one of many possible ways. E.g., the exit function in C returns no value, but it has the side effect of aborting the application. Another example, a C++ class may have a void method that changes the value of its instance variables.
void() means return nothing.
void doesn't mean nothing. void is a type to represent nothing. That is a subtle difference : the representation is still required, even though it represents nothing.
This type is used as function's return type which returns nothing. This is also used to represent generic data, when it is used as void*. So it sounds amusing that while void represents nothing, void* represents everything!
Because sometimes you dont need a return value. That's why we use it.
If you didn't have void, how would you tell the compiler that a function doesn't return a value?
Cause consider some situations where you may have to do some calculation on global variables and put results in global variable or you want to print something depending on arguments , etc.. In these situations you can use the method which dont return value.. i.e.. void
Here's an example function:
struct SVeryBigStruct
{
// a lot of data here
};
SVeryBigStruct foo()
{
SVeryBigStruct bar;
// calculate something here
return bar;
}
And now here's another function:
void foo2(SVeryBigStruct& bar) // or SVeryBigStruct* pBar
{
bar.member1 = ...
bar.member2 = ...
}
The second function is faster, it doesn't have to copy whole struct.
probably to tell the compiler " you dont need to push and pop all cpu-registers!"
Sometimes it can be used to print something, rather than to return it. See http://en.wikipedia.org/wiki/Mutator_method#C_example for examples
Functions are not required to return a value. To tell the compiler that a function does not return a value, a return type of void is used.

Under what scenarios would you declare a non-reference, non-pointer type function parameter const?

I have the following function declaration:
void fn(int);
This function has a single integral type parameter. Now, I could call this function by passing a non const or a const integral object. In either case, this function is going to copy the object to its local int parameter. Therefore, any modifications to this parameter is going to be local to the function and is not going to affect the actual arguments of the caller in any way. Now my question is under which scenario will I declare this single int parameter to be of const type? I don't see a need to declare this function as follows.
void fn(const int);
This is because the arguments are going to be anyway passed by value and the function can in no way modify the arguments in either case. I understand that by declaring a parameter constant the function cannot modify it inside its body. However, there is no downside here even if the function modifies since the parameter is local to the function.
You're right that to the caller there is no difference -- it only matters inside the function. I prefer to add the const whenever I can. As I'm writing the function, I'm thinking "I want this parameter but have no intention of modifying it (even just locally)" and the compiler will keep me honest.
Also, in some cases the compiler may be able to do more optimizations if it knows the variable is const (as in loop bounds).
Just because it's allowed, doesn't mean there's a point to it.
I wouldn't be surprised if this could cause overloading to behave slightly differently, but I think you're basically right - there's no good outside-the-function reason to do it.
One possible problem is confusing readers who might think you intended a reference instead, but forgot the "&".
Sometimes templates are written in a general way, and end up doing things like that. With function template parameter deduction, though, that const tends to get thrown away.
this is effectively a const argument. It is a pointer, but it's immutable in the sense of your example. (Of course, this is a keyword, not a variable, and unary & doesn't work with it.) If you want an argument to behave like that, declare it const.
From the C++ Spec: http://www.kuzbass.ru:8086/docs/isocpp/over.html
Parameter declarations that differ
only in the presence or absence of
const and/or volatile are equivalent.
That is, the const and volatile
type-specifiers for each parameter
type are ignored when determining
which function is being declared,
defined, or called.
Example:
typedef const int cInt;
int f (int);
int f (const int); // redeclaration of f(int)
int f (int) { ... } // definition of f(int)
int f (cInt) { ... } // error: redefinition of f(int)
A favorite interview question in C++ interview is what is the difference between passing by values, passing by pointer and passing by reference.
In this case we are passing by value and that too int and hence it will not matter. But I am not sure about the user created classes. In that case when the compiler see the object is passed by const value it may decide to pass it by the const reference. Nowdays compilers are intelligent and I don't see why they can not do it.