Related
This question already has answers here:
What's the difference between passing by reference vs. passing by value?
(18 answers)
Closed 6 years ago.
I am new to programming and here is a simple question about how passing by reference works. In this program, I am calculating roots of a quadratic equation.
void getCoefficients(double &a, double &b, double &c);
void solveQuadratic(double a, double b, double c, double &x1, double &x2);
void printRoots(double x1, double x2);
void error(string msg);
int main() {
double a,b,c,x1,x2;
getCoefficients(a,b,c);
solveQuadratic(a,b,c,x1,x2);
printRoots(x1,x2);
return 0;
}
So, my question is I seem to be passing values to getCoefficients and solveQuadratic from main program but in the function definitions of getCoefficients and solveQuadratic, I seem to be accepting references as arguments and am confused as to how this works?
When passing a variable by reference, whatever changes you make to it in the function are reflected back in the calling function.
On the other hand, when you pass a variable by value, the changes made to it are local, and hence not reflected in the calling function.
For example,
#include "iostream"
using namespace std;
void function1(int &x, int y) // x passed by reference
{
x+=y;
}
void function2(int x, int y) // x passed by value
{
x+=y;
}
int main()
{
int x=10;
function1(x, 10); // x is passed by reference (no & while calling)
cout << x << endl; // 20
function2(x, 1000);// x is passed by value
cout << x << endl; // 20
}
Notice that whatever value of y you pass in the call to function2 does not make any difference to the second cout statement.
You do not decide whether to pass values or references in main. The function definition decides that for you. Irrespective of pass by value or pass by reference, the format of calling a function remains the same.
void getCoefficients(double &a, double &b, double &c);
This says, "I take 3 parameters - all of the type double & (reference to a double). Reference is quite a lot confused with pointers, so I recommend you read this up first.
Let's call the a,b,c inside the main as main_method_vars.
When you call getCoefficients, whatever this function does to the passed variables inside it, is reflected on the main_method_vars. Actually, this method works with the main_method_vars.
If instead you have void getCoefficients(double a, double b, double c), this means that whenever you call this method with the main_method_vars, this method will copy the values of a,b,c and work with new copies, instead of working with the original passed copies to it.
void getCoefficients(double &a, double &b, double &c);
void solveQuadratic(double a, double b, double c, double &x1, double &x2);
For example, function getCoefficients, variable a,b,c is passed by reference, so the value for the three variables will be changed in the main function also, if their value changed in the getCoefficients function.
Although not directly an answer, you could look at the topic "variable scope". It would explain why the symbols "a", "b" and "c" may or may not not represent the same thing in the different functions. The concept of local variables is a prerequisite of understanding of "pass by value", "pass by pointer" and "pass by reference".
You can also do this first test: try changing the names of parameters in one of the functions, for example getCoefficients(double &first,double&second,double &third).
You can also do this second test: try calling solveQuadratic(10, 20, 30, x1,x2) and getCoefficients(1,-2,1). The first should work, but not the second.
Finally, you can try this third test: change the value of arguments x1 and x2 in the printRootsfunction. Then check if these changes also occurred in the main function (after the call to printRoot, of course).
This question already has answers here:
What's the difference between passing by reference vs. passing by value?
(18 answers)
Closed 6 years ago.
I am new to programming and here is a simple question about how passing by reference works. In this program, I am calculating roots of a quadratic equation.
void getCoefficients(double &a, double &b, double &c);
void solveQuadratic(double a, double b, double c, double &x1, double &x2);
void printRoots(double x1, double x2);
void error(string msg);
int main() {
double a,b,c,x1,x2;
getCoefficients(a,b,c);
solveQuadratic(a,b,c,x1,x2);
printRoots(x1,x2);
return 0;
}
So, my question is I seem to be passing values to getCoefficients and solveQuadratic from main program but in the function definitions of getCoefficients and solveQuadratic, I seem to be accepting references as arguments and am confused as to how this works?
When passing a variable by reference, whatever changes you make to it in the function are reflected back in the calling function.
On the other hand, when you pass a variable by value, the changes made to it are local, and hence not reflected in the calling function.
For example,
#include "iostream"
using namespace std;
void function1(int &x, int y) // x passed by reference
{
x+=y;
}
void function2(int x, int y) // x passed by value
{
x+=y;
}
int main()
{
int x=10;
function1(x, 10); // x is passed by reference (no & while calling)
cout << x << endl; // 20
function2(x, 1000);// x is passed by value
cout << x << endl; // 20
}
Notice that whatever value of y you pass in the call to function2 does not make any difference to the second cout statement.
You do not decide whether to pass values or references in main. The function definition decides that for you. Irrespective of pass by value or pass by reference, the format of calling a function remains the same.
void getCoefficients(double &a, double &b, double &c);
This says, "I take 3 parameters - all of the type double & (reference to a double). Reference is quite a lot confused with pointers, so I recommend you read this up first.
Let's call the a,b,c inside the main as main_method_vars.
When you call getCoefficients, whatever this function does to the passed variables inside it, is reflected on the main_method_vars. Actually, this method works with the main_method_vars.
If instead you have void getCoefficients(double a, double b, double c), this means that whenever you call this method with the main_method_vars, this method will copy the values of a,b,c and work with new copies, instead of working with the original passed copies to it.
void getCoefficients(double &a, double &b, double &c);
void solveQuadratic(double a, double b, double c, double &x1, double &x2);
For example, function getCoefficients, variable a,b,c is passed by reference, so the value for the three variables will be changed in the main function also, if their value changed in the getCoefficients function.
Although not directly an answer, you could look at the topic "variable scope". It would explain why the symbols "a", "b" and "c" may or may not not represent the same thing in the different functions. The concept of local variables is a prerequisite of understanding of "pass by value", "pass by pointer" and "pass by reference".
You can also do this first test: try changing the names of parameters in one of the functions, for example getCoefficients(double &first,double&second,double &third).
You can also do this second test: try calling solveQuadratic(10, 20, 30, x1,x2) and getCoefficients(1,-2,1). The first should work, but not the second.
Finally, you can try this third test: change the value of arguments x1 and x2 in the printRootsfunction. Then check if these changes also occurred in the main function (after the call to printRoot, of course).
I tried searching everywhere, but because it is such a perplexing question, I wasn't able to find what I was looking for. I am trying to create function/method but I don't know how to specify its return type, which should be:
double(*)[3]
I want to be able to use a query like this one:
double R[3][3];
query ( &output, R );
but instead of R[3][3], I have a vector std::vector<double> R_vect (9); and I do this:
query ( &output, reinterpret_cast<double(*)[3]> (R_vect.data()) );
which is a mess, so I wanted to implement a function to make it readable, say:
ReturnType Cast ( const std::vector<double>& R_vect ) {
return reinterpret_cast<double(*)[3]> (R_vect.data());
}
but I can't specify the return type.
I used typedef, and it works:
typedef double DesiredCast[3];
DesiredCast* Cast ( ... ) { ... }
but I am still curious how to do it without typedefs.
You should always typedef complicated return types like these, rather than require the reader to untangle them. (or redesign so you don't have complicated types!)
But you can just follow the pattern. To declare a variable of this type you would do
double (*var)[3];
and to make it a function you just put the usual decoration in the usual place next to the name, despite horrible it seems. e.g. with an int argument named z:
double (*func(int z))[3]
{
// ...
}
Incidentally, cdecl will do that for you, once you learn its language.
It's pretty bizarre syntax:
double (*foo(void))[3]
{
static double f[3][3];
return f;
}
I'm having a function which computes some averages of some values as inputs and the outputs are two ways of computing average: normal average and logarithmic mean.
void average_function(double nb1, double nb2, double &avr1, double &avr2)
{
....
}
in the main program: I just want to call just the first return, I mean, avr1, and I don't want to have the output avr2. I think if it's a pointer, you shall put to avr2=NULL but not in that case.
double avr1;
average_function(nb1, nb2, avr1, avr2)
Is there a way to output just avr1 in that situation? Or, I shall seperate the different average functions to two ones: one to return avr1 and the other to return avr2 (something that I really don't want to do).
You should separate these into 2 functions. And you should return results to the caller with (shockingly?) a return value...
double Average(double nb1, double nb2);
double LogarithmicMean(double nb1, double nb2);
I would definitely break it up in two functions, and have the average as the return parameter of those functions, such as:
double normalAverage(double nb1, double nb2);
double logarithmicMean(double nb1, double nb2);
...
double normalAvg = normalAverage(15.25, 99.12);
double logMean = logarithmicMean(15.25, 99.12);
There are solutions, none of which is particularly beatuiful (in fact I find both questionable). But for educational purposes:
You can make a functionally overloaded function that discards the 2nd parameter
void average_function(double nb1, double nb2, double &avr1, double &avr2)
{
....
}
void average_function(double nb1, double nb2, double &avr1)
{
double dummy;
average_function(nb1, nb2, avr1, dummy);
}
Further, if you define a global double value somewhere, you could use it as a default parameter:
static double dummy;
void average_function(double nb1, double nb2, double &avr1, double &avr2= dummy)
{
....
}
Passing the argument as pointer, and not computing the corresponding mean if it is nullptr is quite common and absolutely ok.
Design-wise, you should probably split the functionality into two functions, though. My response is based on your saying that you don't want to do this. The only reason you could have for keeping it in one function is if the amount of data to be processed is so large that it blows away the CPU caches, and it therefore would be desirable to only traverse once.
The & operator, when used in a function declaration, is the reference operator. It means that any parameters passed into your function are passed by reference, which means any changes made by the function to the value are kept after the function is concluded. (parameters passed into your function the normal way, by value, are effectively copied into the function; any changes the function makes will not apply to the outside value). A reference is not quite a pointer, which is why you can't pass it NULL.
The best choice is to separate the functions. It's best to make each function be supposed to do one "thing", and if there is a distinct thing to do, do it differently.
If you'd still like to use only one function, you can pass an invalid value to &avr2 (such as 0, if that is in fact invalid), and within the function whether it is 0 or not; if it is, perform the function operation that does not involve using &avr2. If it isn't 0, use &avr2.
void average_function(double nb1, double nb2, double &avr1, double &avr2)
{
if(avr2==0)
{
//non-avr2 option
} else {
//avr2 option
}
}
int add (int x, int y=1)
int main ()
{
int result1 = add(5);
int result2 = add(5, 3);
result 0;
}
VS
int add (int x, int y)
int main ()
{
int result1 = add(5, 1);
int result2 = add(5, 3);
result 0;
}
What is the advantage of using the default function parameter, in term of execution speed, memory usage and etc? For beginner like me, I sometimes got confused before I realized this usage of default function parameter; isn't it coding without default function parameter made the codes easier to read?
Your add function is not a good example of how to use defaulted parameters, and you are correct that with one it is harder to read.
However, this not true for all functions. Consider std::vector::resize, which looks something like:
template<class T>
struct vector_imitation {
void resize(int new_size, T new_values=T());
};
Here, resizing without providing a value uses T(). This is a very common case, and I believe almost everyone finds the one-parameter call of resize easy enough to understand:
vector_imitation<int> v; // [] (v is empty)
v.resize(3); // [0, 0, 0] (since int() == 0)
v.resize(5, 42); // [0, 0, 0, 42, 42]
The new_value parameter is constructed even if it is never needed: when resizing to a smaller size. Thus for some functions, overloads are better than defaulted parameters. (I would include vector::resize in this category.) For example, std::getline works this way, though it has no other choice as the "default" value for the third parameter is computed from the first parameter. Something like:
template<class Stream, class String, class Delim>
Stream& getline_imitation(Stream &in, String &out, Delim delim);
template<class Stream, class String>
Stream& getline_imitation(Stream &in, String &out) {
return getline_imitation(in, out, in.widen('\n'));
}
Defaulted parameters would be more useful if you could supply named parameters to functions, but C++ doesn't make this easy. If you have encountered defaulted parameters in other languages, you'll need to keep this C++ limitation in mind. For example, imagine a function:
void f(int a=1, int b=2);
You can only use the given default value for a parameter if you also use given defaults for all later parameters, instead of being able to call, for example:
f(b=42) // hypothetical equivalent to f(a=1, b=42), but not valid C++
If there is a default value that will provide correct behavior a large amount of the time then it saves you writing code that constantly passes in the same value. It just makes things more simple than writing foo(SOME_DEFAULT) all over the place.
It has a wide variety of uses. I usually use them in class constructors:
class Container
{
// ...
public:
Container(const unsigned int InitialSize = 0)
{
// ...
}
};
This lets the user of the class do both this:
Container MyContainer; // For clarity.
And this:
Container MyContainer(10); // For functionality.
Like everything else it depends.
You can use it to make the code clearer.
void doSomething(int timeout=10)
{
// do some task with a timeout, if not specified use a reasonable default
}
Is better than having lots of magic values doSomething(10) throughout your code
But be careful using it where you should really do function overloading.
int add(int a)
{
return a+1;
}
int add(int a,int b)
{
return a+b;
}
As Ed Swangren mentioned, some functions have such parameters that tend to have the same value in most calls. In these cases this value can be specified as default value. It also helps you see the "suggested" value for this parameter.
Other case when it's useful is refractoring, when you add some functionality and a parameter for it to a function, and don't want to break the old code. For example, strlen(const char* s) computes the distance to the first \0 character in a string. You could need to look for another characted, so that you'll write a more generic version: strlen(const char* s, char c='\0'). This will reuse the code of your old strlen without breaking compatibility with old code.
The main problem of default values is that when you review or use code written by others, you may not notice this hidden parameter, so you won't know that the function is more powerful than you can see from the code.
Also, google's coding style suggests avoiding them.
A default parameter is a function parameter that has a default value provided to it. If the user does not supply a value for this parameter, the default value will be
used. If the user does supply a value for the default parameter, the user-supplied value is used.
In computer programming, a default argument is an argument to a function that a programmer is not required to specify. In most programming languages, functions may take one or more arguments. Usually, each argument must be specified in full (this is the case in the C programming language)
Advantages of using default parameter, as others have pointed out, is indeed the "clarity" it brings in the code with respect to say function overloading.
But, it is important to keep in mind the major disadvantage of using this compile-time feature of the language: the binary compatibility and default function parameter does not go hand in hand.
For this reason, it is always good to avoid using default params in your API/interfaces classes. Because, each time you change the default param to something else, your clients will need to be recompiled as well as relinked.
Symbian has some very good C++ design patterns to avoid such BC.
Default parameters are better to be avoided.
let's consider the below example
int DoThis(int a, int b = 5, int c = 6) {}
Now lets say you are using this in multiple places
Place 1: DoThis(1);
Place 2: DoThis(1,2);
Place 3: DoThis(1,2,3);
Now you wanted to add 1 more parameter to the function and it is a mandatory field (extended feature for that function).
int DoThis(int a, int x, int b =5, int c=6)
Your compiler throws error for only "Place 1". You fix that. What about other others?
Imagine what happens in a large project? It would become a nightmare to identify it's usages and updating it rightly.
Always overload:
int DoThis(int a) {}
int DoThis(int a, int b {}
int DoThis(int a, int b, int c) {}
int DoThis(int a, int b, int c, int x) {}