Call-by-value example

Pages: 12
Hi cplusplus forum, could you help clarify 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?
That's because the function is using "call by value" which means it makes a local copy of the value you pass, instead of modifying the original value.
You should pass your value by reference, or using a pointer:
1
2
3
4
5
6
// Pass By Reference
void changeValue(int &value);
void changeValue(int &value)
{
    value = 6;
}

1
2
3
4
5
6
7
8
9
10
// Pass By Pointer, you should call this function like:
// changeValue(&value)
// in your code
void changeValue(int * value);
void changeValue(int * value)
{
    if(!value)
        return 0;
    *value = 6;
}
EssGeEich wrote:
1
2
3
4
5
6
7
8
9
10
// Pass By Pointer, you should call this function like:
// changeValue(&value)
// in your code
void changeValue(int * value);
void changeValue(int * value)
{
    if(!value)
        return 0;
    *value = 6;
}


You can't return a value in a void function.

Otherwise, I'd suggest using functions by reference. It's harder to forget the pointer character that way. And I might be mistaken, but by reference passes the variable as if it was part of the scope of the function, where as passing by pointer passes the physical memory address of where the variable is stored. I never got the chance to learn the benefits to each, but I guess now is just as good as any.
Last edited on
Well, you are right, my mistake at not noticing it was a Void function.
And, Pass-by-reference is a bit faster than Pass-by-pointer, as a Pass-by-pointer call will have a memcpy of ( sizeof( void * ) /* Size of any pointer */ ) bytes while calling the function.
EssGeEich wrote:
Pass-by-reference is a bit faster than Pass-by-pointer, as a Pass-by-pointer call will have a memcpy ( sizeof( void * ) /* Size of any pointer */ ) bytes while calling the function.

I don't think there has to be a speed difference. The address of the argument still has to be sent to the function, otherwise how can the function manipulate the argument?
Well, consider at first the following example

1
2
3
4
5
int a = 5;
int b;

b = a;
b = 6;


Will be the value of "a" changed in this code? As i can guess the value of "a" will not be changed because we were changing another variable b.

The same is valid for your function.

void changeValue(int value)
{
value = 6;
}

In fact when you call the function

changeValue(value);

it means that variable "value" that is declared as a parameter of a the function is assigned the value of variable "value" that is declared in the main. To simplify understanding let asuume that variable "value" in the main denotes "a" from the example above and the parameter "value" denotes "b" from the same example. So the call

changeValue(value);

is equivalent to

b (that is the parameter value ) = a ( that is the variable in the main);
and further in the body of the function you assign "b" 6. "a' is unchanged.
I don't think there has to be a speed difference. The address of the argument still has to be sent to the function, otherwise how can the function manipulate the argument?

There is. It's really tiny, but THERE IS speed difference. Passing by reference is like adding that code under your Entry Point cleanly, the argument does NOT get copied, where it's pointer, in the pass-by-pointer side, copies the original pointer. Let's say you want to get your pointer's pointer. That's it, a bit complex, but that's the same.
EssGeEich wrote:
Passing by reference is like adding that code under your Entry Point cleanly
I don't understand what you mean by this.

EssGeEich wrote:
the argument does NOT get copied

I know but it still has to give something to the function that it can use to access the argument, right? That something should be pretty much equivalent to a pointer.
So then I ask again, why would someone use pass by pointer over pass by reference? I can understand the char pointer from string, but anything else doesn't make sense to me.
There are not many reasons; one I use now and then is that the pointer can be NULL, and the function I'm passing to can branch depending on that. A reference cannot be null.
closed account (zb0S216C)
Volatile Pulse wrote:
"why would someone use pass by pointer over pass by reference?"

References must refer to something, pointers do not. A pointer is no more superior than a reference, nor is a reference more superior than a pointer.

Wazzak
How can you call a function with an empty pointer? I don't know too much about the memory applications of things, other than what I need to get by. If I'm not mistaken the pointer pots to a specific spot in memory where that variable exists. How can a variable be destroyed but still be able to be passed? Maybe I'm thinking too hard about this, or not thinking hard enough, but I can't conceive a possible way to pass by a null pointer.
closed account (zb0S216C)
An empty pointer? What's that? A null pointer?

Volatile Pulse wrote:
"If I'm not mistaken the pointer pots to a specific spot in memory where that variable exists." (sic)

Yes, that's right.

Volatile Pulse wrote:
"How can a variable be destroyed but still be able to be passed?"

You can't and you should not. Automatic objects are destroyed as soon as the scope in which they reside is destroyed. Any pointers pointing to a recently destroyed object are invalidated; an attempt to dereference an invalid pointer can and will cause segmentation faults (accessing memory that isn't associated with your program). References are particularly dangerous in this scenario, because references cannot be reseated (made to refer to another object).

Wazzak
Last edited on
I think you've missed something basic about pointers. A pointer is a unique, free-standing variable that takes up memory and has its own existence and its own value, completely independent of other variables. You can have a pointer that does not point to any variable. You can have a pointer with a nonsense value that points into some random piece of memory.

How can you call a function with an empty pointer?

"Empty" makes no sense. Pointers cannot be empty or full. If a pointer exists, it has a value. That value might be the memory address of a variable you care about, that value might be some random value, it might be NULL.

Here is how you can pass a NULL pointer to a function. You will note it's exactly the same as passing a non-NULL pointer.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <iostream>

void isPointerNull(int * input)
{
  if (input == NULL) { std::cout << "Pointer is null" << std::endl;}
  else { std::cout << "Pointer is not null" << std::endl;}
}

int main()
{
  int* a = NULL;
  int b = 7;
  int* c = &b;

  isPointerNull(a);
  isPointerNull(c);
}


Edited to change a b into a c. THis is what comes of sleeping instead of testing :)
Last edited on
Now I'm really confused, this is why I asked HOW it could be done because you just showed me and my compiler says it can't be done.
Code Blocks wrote:
C:\...\main.cpp||In function 'int main()':|
C:\...\main.cpp|16|error: invalid conversion from 'int' to 'int*'|
C:\...\main.cpp|16|error: initializing argument 1 of 'void isPointerNull(int*)'|
||=== Build finished: 2 errors, 0 warnings ===|
I think Moschops meant to pass "c" into "isPointerNull()", not "b" .. In order to pass "b" in you have to pass in its address as such:

 
isPointerNull(&b); // Read: "Address of b" 
Last edited on
I have a theory. Can someone tell me if it's valid or not.
I was always told that doing this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
int main
{
    int foo = 5;
    callSomeFunction(foo);

    return 0;
}

void callSomeFuction(int &bar)
{
    bar = 6;
    // changes value of foo in main function
    return;
}


was called passing by reference.
However, you don't pass an address. Instead, you're just using the reference operator to create an alias of the same memory address. Is it still considered passing by reference, even if you're not passing an adress?
Last edited on
called passing by reference.


That's correct.

However, you don't pass an address. Instead, you're just using the reference operator to create an alias of the same memory address. Is it still considered passing by reference, even if you're not passing an adress?


Don't think of it in relation to addresses at all. Just think of it as "this is how you pass by reference." kind of a thing.
1
2
3
4
5
6
7
8
9
10
11
12
13
int main()
{
    int foo = 5;
    callSomeFunction(foo);

    return 0;
}

void callSomeFuction(int &bar)
{
    bar = 6;
    // changes value of foo in main function
}

Wrong. You should call it like:
1
2
3
4
5
6
int main()
{
    int foo = 5;
    callSomeFunction(&foo);
    return 0;
}
Pages: 12