Why does call-by-value example not modify input parameter? - c++

In the following call-by-value example, I cannot understand why this code is not changing the value of the 5 to a 6.
Line 11 calls the function changeValue which has the value 6, so I would have thought 6 should be output, however 5 is still output?
#include <iostream>
using namespace std;
void changeValue(int value);
int main()
{
int value = 5;
changeValue(value);
cout << "The value is : " << value << "." << endl;
return 0;
}
void changeValue(int value)
{
value = 6;
}
// This doesn't change the value from 5 to 6. 5 is output?

When you pass a function argument by value a copy of the object gets passed to the function and not the original object.Unless you specify explicitly arguments to functions are always passed by value in C/C++.
Your function:
void changeValue(int value)
receives the argument by value, in short a copy of value in main() is created and passed to the function, the function operates on that value and not the value in main().
If you want to modify the original then you need to use pass by reference.
void changeValue(int &value)
Now a reference(alias) to the original value is passed to the function and function operates on it, thus reflecting back the changes in main().

The value of value isn't changing because your int that you pass to the function is being copied into the stack frame of the function, then it's being changed, and when the function exits the copy is destroyed. The original in main's stackframe has not changed, since it was copied to the changeValue.
If you want to change it, you should pass a reference to an int, like so void changeValue(int& value), which says that the value isn't copied into the function, but merely an alias to the original is passed.

The behavior being observed currently is because passing by value means a copy of value (new integer with value of value) is actually passed to the function.
You have to pass by reference. For that the changeValue function will look like this:
void changeValue(int& value)
Rest of the code will remain the same.
Passing a variable by reference means the same int value declared in main is passed to the changeValue function.
Alternatively, you can pass a pointer to value to the changeValue function. That will however, require changes to how you call the function also.
int main()
{
int value = 5;
changeValue(&value);
...
return 0;
}
void changeValue(int* value)
{
*value = 6;
}

I'm including this answer as another way to think about writing functions and passing parameters by value.
You could also have written this code in the following way. That is pass the parameter by value, modify the local copy in the function, which does not alter the original value, and return the altered value.
int changeValue(int val)
{
val = 6;
return val;
}
int main()
{
int value = 5;
value = changeValue(value);
cout << "The value is : " << value << "." << endl;
return 0;
}
I am not in any way indicating my suggestion for your program is better than passing by reference. Instead, it is just the way learning a functional programming language (Clojure) is affecting the way I think.
Also, in languages like Python, you cannot modify a scalar parameter. You can only return a new value. So my answer is more of an exercise in thinking about things differently in C/C++.

AND:
the copy is assigned 6, but the change is not returned.
you need some reference or pointer if you want to change the value:
try using a method signature like:
void changeValue(int& value)
that will probably do what you expected

This is because the change in the changeValue () function is local. When you can changeValue (value) the contents of the variable value in main is copied in the formal argument named value (same name) of the function. Same name does not mean that the both are same. The value you are accessing inside the function is a copy of the value you had in the main.
To change you either need to pass it by reference or a pointer
void changeValue (int *val)
{
*val = 6;
}
call with changeValue (&value) in main
This works because the address of the variable value in main is passed and this address value is copied into val of the function. By doing *val we can get the contents of the address which was copied into val, which in actually the contents of value in main.
OR
void changeValue (int &val)
{
val = 6;
}

Related

friend function is not assigning values to class's array [duplicate]

In the following call-by-value example, I cannot understand why this code is not changing the value of the 5 to a 6.
Line 11 calls the function changeValue which has the value 6, so I would have thought 6 should be output, however 5 is still output?
#include <iostream>
using namespace std;
void changeValue(int value);
int main()
{
int value = 5;
changeValue(value);
cout << "The value is : " << value << "." << endl;
return 0;
}
void changeValue(int value)
{
value = 6;
}
// This doesn't change the value from 5 to 6. 5 is output?
When you pass a function argument by value a copy of the object gets passed to the function and not the original object.Unless you specify explicitly arguments to functions are always passed by value in C/C++.
Your function:
void changeValue(int value)
receives the argument by value, in short a copy of value in main() is created and passed to the function, the function operates on that value and not the value in main().
If you want to modify the original then you need to use pass by reference.
void changeValue(int &value)
Now a reference(alias) to the original value is passed to the function and function operates on it, thus reflecting back the changes in main().
The value of value isn't changing because your int that you pass to the function is being copied into the stack frame of the function, then it's being changed, and when the function exits the copy is destroyed. The original in main's stackframe has not changed, since it was copied to the changeValue.
If you want to change it, you should pass a reference to an int, like so void changeValue(int& value), which says that the value isn't copied into the function, but merely an alias to the original is passed.
The behavior being observed currently is because passing by value means a copy of value (new integer with value of value) is actually passed to the function.
You have to pass by reference. For that the changeValue function will look like this:
void changeValue(int& value)
Rest of the code will remain the same.
Passing a variable by reference means the same int value declared in main is passed to the changeValue function.
Alternatively, you can pass a pointer to value to the changeValue function. That will however, require changes to how you call the function also.
int main()
{
int value = 5;
changeValue(&value);
...
return 0;
}
void changeValue(int* value)
{
*value = 6;
}
I'm including this answer as another way to think about writing functions and passing parameters by value.
You could also have written this code in the following way. That is pass the parameter by value, modify the local copy in the function, which does not alter the original value, and return the altered value.
int changeValue(int val)
{
val = 6;
return val;
}
int main()
{
int value = 5;
value = changeValue(value);
cout << "The value is : " << value << "." << endl;
return 0;
}
I am not in any way indicating my suggestion for your program is better than passing by reference. Instead, it is just the way learning a functional programming language (Clojure) is affecting the way I think.
Also, in languages like Python, you cannot modify a scalar parameter. You can only return a new value. So my answer is more of an exercise in thinking about things differently in C/C++.
AND:
the copy is assigned 6, but the change is not returned.
you need some reference or pointer if you want to change the value:
try using a method signature like:
void changeValue(int& value)
that will probably do what you expected
This is because the change in the changeValue () function is local. When you can changeValue (value) the contents of the variable value in main is copied in the formal argument named value (same name) of the function. Same name does not mean that the both are same. The value you are accessing inside the function is a copy of the value you had in the main.
To change you either need to pass it by reference or a pointer
void changeValue (int *val)
{
*val = 6;
}
call with changeValue (&value) in main
This works because the address of the variable value in main is passed and this address value is copied into val of the function. By doing *val we can get the contents of the address which was copied into val, which in actually the contents of value in main.
OR
void changeValue (int &val)
{
val = 6;
}

Looking for an explanation on why this C++ code does not work without references

I'm a beginner learning C++ and reached a chapter regarding passing arguments by references. There was a swap function defined as such:
void swap(double& d1, double& d2)
{
double temp = d1;
d1 = d2;
d2 = temp;
}
The test was this, and it worked, with values swapped:
int main()
{
double x = 1;
double y = 2;
cout << "X==" << x << "y==" << y << '\n';
swap(x,y);
cout << "x==" << x << "y==" << y << '\n';
}
However I can't for the life of me figure out why removing the references makes this code do nothing:
void swap(double d1, double d2)
{
double temp = d1;
d1 = d2;
d2 = temp;
}
I've done this since I wanted to better understand references since properly understanding them eludes me. I would appreciate an answer or a pointer in the right direction.
There are common notions in procedural programming languages like C++ of "pass by value" and "pass by reference".
When a variable is passed by value into a procedure (or function) a copy is made of the variable and any modifications made in the procedure (or function) don't reflect in the variable passed by value.
Conversely, when a variable is passed by reference modifications are reflected in the variable that was passed by reference.
The term reference in C++ refers to that idea so in the reference case the actions of swap() do swap the original variables passed as arguments, in the second case they don't.
If you see a function void foo(int x) called as foo(b); you should read that as "make a copy of b and perform foo on that copy".
If it were void foo(int &x) it would be "perform foo directly on b.
Lets use an analogy... you have a piece of paper with two numbers written on it. Now you want a friend to swap the two values. This:
void swap(double d1, double d2) {
double temp = d1;
d1 = d2;
d2 = temp;
}
is like you take a second piece of paper, write the numbers on it, give it to your friend (pass-by-value), he swaps the value but returns nothing to you (void return type). Will that change change the numbers on your piece of paper? No.
Lets change the strategy: Instead of giving your friend a copy of your numbers, you now tell him where he can find your piece of paper so he can do the job directly on that (pass-by-reference):
void swap(double& d1, double& d2) {
double temp = d1;
d1 = d2;
d2 = temp;
}
He still does not have to return anything to you, because once he is done you just have to look at your piece of paper to see the values swapped.
PS: analogies always have their limit, so take it with a grain of salt.
Passing a reference is like passing "the thing itself", not just its value.
It works kind of like if you handed a friend your precious ring, let them muck around with it in whatever way, and then got it back.
Passing by value is like handing a friend a different ring that looks exactly like your precious ring and they get to keep it, and you keep yours, untouched by their filthy, thieving fingerses.
A simpler example than swap:
void fv(int x)
{
x = 0;
}
If you pass a variable to this, that variable's value is copied into the completely indepent variable x.
x will have the same value as your variable, but it will not be the same thing.
When you assign a value to x, you're assigning to this variable, not to the one whose value was copied into it.
void fr(int& x)
{
x = 0;
}
If you pass a variable to this - fr(v) - x is your variable; the names "x" and "v" refer to the same thing.
Assigning a value to x inside the function is exactly the same as assigning a value to v in the calling code.
In the first example, you are passing the doubles as reference. Altering the values inside the function, changes the double x & y in your main.
In the second example, you are passing the doubles as value. This means, their value is copied ie. two new doubles are created and passed to the function. By changing those values, you modify the copied doubles - and not x & y from your main.
Because by default, when you pass a variable as a function argument, it's passed by value. That means that (like in a code below) when passed to the function, it actually creates a copy of it and you no longer work with the original variable and you operate with its copy - it has the same value but different location in memory.
int myVar = 10;
void f(int var) {
var = 20;
}
// here the value of myVar is 10
f(myVar);
// here the value of myVar is still 10
Passing variable by its reference is there exactly because of the example you showed. You want to create a function that can actually modify the value of a passed variable outside of the scope of the function.
int myVar = 10;
void f(int& var) {
var = 20;
}
// here the value of myVar is 10
f(myVar);
// here the value of myVar is still 20
You can think of it as a definition
I want to pass the variable to a function and I don't want it to change its value outside the function - use raw type - pass it by value
I want to pass the variable to a function and I want it to change its value outside the function - use & - pass it by reference
This is very often used when working with strings. For example: let's assume you get packet data in a variable std::string packet and you want to create a function that analysis it. You can do something like this
std::string packet;
someResultType func(std::string packet) {
....
}
auto result = function(packet);
But in this example, it is totally useless to create a new copy of variable packet because when working with it, you probably won't modify it, so you say to the compiler - I promise I won't modify the value thus you can pass the value by reference:
std::string packet;
someResultType func(const std::string& packet) {
// you're working with the global packet but you cant modify it
}
auto result = function(packet);

Changing address of variables using reference

in below code why its displaying 2,3 though we change the address. why not 3,2.
#include <iostream>
using namespace std;
void Addresschange(int *a, int *b)
{
int *t;
t = a;
a = b;
b = t;
cout << *a<<endl<< *b<<endl;//here its displaying 3,2
}
int main ()
{
int a = 2 ,b = 3;
Addresschange(&a ,&b);
cout << a<<endl<< b;//why its displaying 2,3 here
return 0;
}
So after going out of this function the addresses of the actual parameters (a and b) would be changed. Is it possible at all?
In the Addresschange function, a and b are local variables. When you change their values, that only changes their values inside the function. So your code just swaps the values of a and b inside the Addresschange function. It doesn't use any pointer operations, so even though the values happen to be pointers. that doesn't change the fact that they're passed by value and that means that changing the value won't propagate out of the function.
If you want to change something's value using a pointer, you have to pass a pointer to it and change the value the pointer points to. So if you want to change the value of an int *, you need to pass the function an int **.
Your function passes an int * (pointer to int), which lets you change the value of an int. For example, *a = 3; will make a equal to 3 instead of 2 in the caller, using the pointer that was passed by value to change the value of the thing it points to.
(You can also use references in C++. You still can't "reseat" a reference to make it refer to something else unless you use something like std::reference_wrapper.)

Why isn't my loop terminating?

newbie question here, can anybody provide an answer to why this loop is not terminating? I am refrencing the address of the variable, then de-referencing it and adding one to it. By my logic it should terminate by ~ the 10th step.
Thanks!
#include <iostream>
using namespace std;
int addtoi(int intern);
int main(){
for(int i = 0; i < 10;addtoi(i)){
}
}
int addtoi(int intern){
int *pt;
pt = &intern;
++*pt;
cout << *pt << "\t" << intern << "\n";
return 0;
}
Your loop is not terminating because any changes that you made to intern inside addtoi stay inside addtoi. The fact that you take a pointer there has no effect, because it's too late: you are taking a pointer of a local variable, which is a copy of i passed in.
You can fix this by passing in intern by reference, like this:
int addtoi(int& intern) {
intern++;
cout << intern << "\n";
return 0;
}
You do not need to take its address - simply modifying it will change the value of i inside the loop.
You don't change the value of i anywhere in your loop. You do pass its value to addtoi, but passing a value can't change the value of the variable whose value you took. So why would it ever end?
If you pass a reference or pointer to i to addtoi, then it can change i's value. But if you only pass the value itself, then it can only change the value passed to it, which has no effect on i's value.
What do you think would happen if you did this:
addtoi(1);
Do you think that constant 1 would somehow change? Same thing -- if you pass a value, you can't change anything in the caller since all you got was a value.
Consider:
int j = 1;
int i = 1;
addtoi(i);
addtoi(j);
addtoi(1);
These three calls all pass the same value to addtoi, 1. It makes no difference how you obtain that value if all you pass is the value.
The loop is not terminating because when you do addtoi(i), the value of i is send to the addtoi() function and not the original i variable. Its a classic example of pass by value.

Returning function parameter, possible, bad style?

So I just had a thought, is it possible to return a parameter sent when a function is called. And if it is, is this considered fine or is it bad style?
Example:
int main()
{
...
int value = 1;
value = Foo(value);
...
}
int Foo(int i)
{
i = i * 2;
return (i);
}
As the parameter is being passed in and returned by value, this is fine - there is an implicit copy occurring when you call the function and when it returns.
For example
int value=1,other=0;
other=Foo(value);
other is now 2, value will still be 1
If you were passing in a reference or pointer then you would potentially run risks.
e.g. if the signature of Foo was
int Foo( int &i )
Then after the code chunk I used above, both other and value would be 2
There's no problem with "returning a parameter" in your example. You are not really "returning a parameter" at all. You are simply using the parameter in the argument expression of return. It is the result of that expression (the value of i) that gets returned, not the parameter itself.
One can argue that the "undesirable" property of your code sample is the fact that you are modifying the parameter inside the function, i.e. you are using the parameter as an ordinary local variable. There's nothing formally wrong with it, but sometimes people prefer to preserve the original parameter values throughout the function body. I.e. from that point of view your function would look better as
int Foo(int i)
{
return i * 2;
}
or as
int Foo(int i)
{
int i2 = i * 2;
return i2;
}
but, again, it is not really about "not returning a parameter", but rather about leaving the original value of i untouched inside the function.
There's no problem with doing that and it makes it very clear what's going on.
That's one valid approach to do this, but you might also like the idea of passing by reference:
int main()
{
...
int value = 1;
Foo(value);
...
}
void Foo(int &i)
{
i = i * 2;
}
The drawback to this approach is that you have to pass what's called an lvalue into the function-- basically, something that can be on the left side of an assignment statement, which here means a variable. A call with a literal or temporary, such as Foo(2), will fail to compile. The way you had written it originally will instead do an implicit copy by value into the local scope of the Foo function. Note that the return value is now also void.
Technically, there is no problem, but semantically, it is not advisable: in most cases the input of the function and the return value of the function are not the same, so you are reusing the variable to mean something different. It is clearer in next example
int main()
{
double i = 5;
i = getSquareSurface(i); // i was a length and is now a surface
}
This should be:
int main()
{
double length = 5;
double surface = getSquareSurface(length);
}
Of course, there are cases like the addOne() or in this case the Foo() function where the meaning doesn't change.