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).
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).
I am new to C++ and have done only MATLAB earlier.
My Q is about the input argument of the following functions, which call variables by value,reference and pointer.
void SwapbyValue (int a, int b){
// Usual swapping code
}
void SwapbyRef (int &a, int &b){
// Usual swapping code
}
void SwapbyPoint(int *a,int *b){
//Usual swapping code
}
Since my Q isn't about how the above functions work but rather about how I call them, I've left out the code. So, I understand we call the above functions by typing SwapbyRef (i1,i2),SwapbyRef (i1,i2) and SwapbyPoint(&i1,&i2) when i1 and 12 are int.
That confuses me the life out of me. Okay, I get that the first function takes in values and makes sense. But in the second one, calling by just i1 and i2 doesn't make sense as when the function is defined, we set its input as &a and not just a but it still runs. Again in the third, we set the input argument as a pointer i.e. *a but we're passing an address &a (like 0x7956a69314d8) when we call it.
Why does it run when we pass the wrong kind of input to the function?
For example,a Matlab analogy,it looks like passing a char to a int function. Help!
int &a is a reference to an int, meaning, it will accept all int variables that already exist. What you cannot do is for example SwapbyRef(4, 5) using SwapbyRef (int &a, int &b), because 4 and 5 are temporary ints that do not exist somewhere in memory as variables.
Btw, you should probably just look up what a reference in c++ is. That would help you most, I think.
I have a function that takes a double *result. I am aware that pointers need to be passed by reference in a function. When I call the function void ComputeSeriesPointer(double x, int n, double *result); in main with ComputeSeriesPointer(x, n, &result);, I get the error:
cannot convert ‘double**’ to ‘double*’ for argument ‘3’ to ‘void ComputeSeriesPointer(double, int, double*)’
ComputeSeriesPointer(x, n, &result);
^
When working with pointers, aren't they all passed using the & key? The in class examples were all done this way. Even on the internet things were done this way. Any explanation/clarification would be great.
I am also running this with a c++ compiler (as instructed by my professor) because I am using the pow function.
I'm not sure about what you are doing without seeing the complete code, but If you are doing something like this:
void ComputeSeriesPointer(double, int, double*){
// ...
}
int main(){
double *x = ...;
ComputeSeriesPointer(1.0, 1, &x);
// ...
return 0;
}
Then, the problem is the &x. The & operator is used to extract a variable address. In this case, your variable is already a pointer, so writing &x you are getting a "pointer to pointer", in other words, a double**. That's your problem. Call your function in this way: ComputeSeriesPointer(1.0, 1, x)
The function is expecting you to pass the memory address of an actual double variable, not the memory address of a double* pointer variable:
double result; // NOT double*!
ComputeSeriesPointer(x, n, &result);
You can also do this:
double result; // NOT double*!
double *presult = &result;
ComputeSeriesPointer(x, n, presult);
The error message implies that the type of result is already double *. You don't need to use the & operator if the variable is already a pointer of the appropriate type. So you should do
ComputeSeriesPointer(x, n, result);
Either that, or you need to change the declaration of the result variable in the caller from double * to double.
It is likely that you are doing this:
double *myNewResult;
...
ComputeSeriesPointer(x, n, &myNewResult);
By doing this you are passing the address of a double* not double. You dont need double *myNewResult, just double myNewResult. Or if you need myNewResult to be a double* you can just pass it to the function like this:
ComputeSeriesPointer(x, n, myNewResult);
The function is declared like
void ComputeSeriesPointer(double, int, double*);
its third parameter has type double *
But you call the function like
ComputeSeriesPointer(x, n, &result);
where the third argument has type double **
You need to call the function like
ComputeSeriesPointer(x, n, result);
Or change the function declaration and correspondingly its definition such a way that the third parametr had type double **
void ComputeSeriesPointer(double, int, double **);
Passing a pointer into a function is passing by reference; the pointer is the "reference." (C++ muddied waters a little bit by also introducing a "reference" type which pretends it is not a pointer, but that's not relevant to the code example you've given.)
The & operator means "address of." It takes a thing and returns a pointer to that thing. So,
double x = 1; // this is a double
double *pointer_to_x = &x;
double **pointer_to_pointer_to_x = &pointer_to_x;
and so on.
We need to see a little bit more of your code calling ComputeSeriesPointer() to answer properly, but my guess is that you have:
double *result; // this kind of variable stores *the address of* a double-precision number.
ComputeSeriesPointer( x, n, &result );
but you really want:
double result; // this kind of variable stores a double-precision number.
ComputeSeriesPointer( x, n, &result );
so that you are passing in the address that you want ComputeSeriesPointer() to write a result into.
my question is:
I saw(in CUDA examples) that it is possible to use one of the input arguments of a function as output variable. Example: add two integers, c=a+b:
void function AddT(int a,int b,int c){
c=a+b;
}
But this will not work. The function will not alter the value of c in the main program. Who can I fix it and allow the function to change the value of c?
Pass the variable c by reference.
void function AddT(int a, int b, int& c)
{
c = a + b;
}
This will make it so that any changes to c that you make in the function will remain even after the function ends. My wording is pretty poor here; you can look here for more information:
Pass by Reference / Value in C++
What's the difference between passing by reference vs. passing by value?
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
}
}