I understand as with any other variable, the type of a parameter determines the interaction between the parameter and its argument. My question is that what is the reasoning behind why you would reference a parameter vs why you wouldn't? Why are some functions parameters reference and some are not? Having trouble understanding the advantages of doing so, could someone explain?
To pass a value by reference, argument pointers are passed to the functions just like any other value. So accordingly you need to declare the function parameters as pointer types as in the following function swap(), which exchanges the values of the two integer variables pointed to, by their arguments.
Pass-by-reference means to pass the reference of an argument in the calling function to the corresponding formal parameter of the called function. The called function can modify the value of the argument by using its reference passed in.
When you pass an argument by reference, you pass a pointer to the value in memory. The function operates on the argument. When a function changes the value of an argument passed by reference, the original value changes. When you pass an argument by value, you pass a copy of the value in memory.
The ability to pass by reference exists for two reasons:
Example for modifying the argument
void get5and6(int *f, int *s) // using pointers { *f = 5; *s = 6; }
this can be used as:
int f = 0, s = 0; get5and6(&f,&s); // f & s will now be 5 & 6
OR
void get5and6(int &f, int &s) // using references { f = 5; s = 6; }
this can be used as:
int f = 0, s = 0; get5and6(f,s); // f & s will now be 5 & 6
When we pass by reference, we pass the address of the variable. Passing by reference is similar to passing a pointer - only the address is passed in both cases.
For eg:
void SaveGame(GameState& gameState) { gameState.update(); gameState.saveToFile("save.sav"); } GameState gs; SaveGame(gs)
OR
void SaveGame(GameState* gameState) { gameState->update(); gameState->saveToFile("save.sav"); } GameState gs; SaveGame(&gs);
Also, read on const
references. When it's used, the argument cannot be modified in the function.
This article helped me a lot.
Please forget about pointers for now. And take this with a grain of salt.
A reference is the object. When you pass by reference, you pass the object.
When you pass by value, you pass a copy of the object; another object. It may have the same state, but it is a different instance; a clone.
So, it may make sense to pass by reference if you:
const
reference.And it may make sense to pass by value if you:
int
by reference unless I wanted to modify it).Here, have a look at this code:
#include<iostream> struct Foo { Foo() { } void describe() const { std::cout<<"Foo at address "<<this<<std::endl; } }; void byvalue(Foo foo) { std::cout<<"called byvalue"<<std::endl; foo.describe(); } void byreference(Foo& foo) { std::cout<<"called byreference"<<std::endl; foo.describe(); } int main() { Foo foo; std::cout<<"Original Foo"<<std::endl; foo.describe(); byreference(foo); byvalue(foo); }
And compile it like this: g++ example.cpp
Run it: ./a.out
And check the output (the actual addresses may be different in your computer, but the point will remain):
Original Foo Foo at address 0x7fff65f77a0f called byreference Foo at address 0x7fff65f77a0f called byvalue Foo at address 0x7fff65f779f0
Notice how the called byreference
address is the same as the Original Foo
address (both are 0x7fff65f77a0f
). And notice how the called byvalue
address is different (it is 0x7fff65f779f0
).
Take it up a notch. Modify the code to look as follows:
#include<iostream> #include<unistd.h> // for sleeping struct Foo { Foo() { } Foo(const Foo&) { sleep(10); // assume that building from a copy takes TEN seconds! } void describe() const { std::cout<<"Foo at address "<<this<<std::endl; } }; void byvalue(Foo foo) { std::cout<<"called byvalue"<<std::endl; foo.describe(); } void byreference(Foo& foo) { std::cout<<"called byreference"<<std::endl; foo.describe(); } int main() { Foo foo; std::cout<<"Original Foo"<<std::endl; foo.describe(); byreference(foo); byvalue(foo); }
Compile it the same way, and notice the output (comments not in the output; included for clarity):
Original Foo Foo at address 0x7fff64d64a0e called byreference Foo at address 0x7fff64d64a0e # this point is reached "immediately" called byvalue # this point is reached TEN SECONDS later Foo at address 0x7fff64d64a0f
So, the code is meant to exaggerate the cost of a copy: when you called by reference this cost was NOT incurred. When you called by value you had to wait for ten seconds.
Note: my code was compiled in OS X 10.7.4 using GCC 4.8.1. If you are in windows you may need something different from unitsd.h
to make the sleep
call work.
Maybe this helps.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With