I’m a function, perhaps I’m main(). I have an integer named Nicky, which has a value of 4. I want that value doubled, and there’s a couple of ways I can have it done. I could just do it myself, but that’s too much work, so I’m going to call a function.
By Value
One way is to use a by-value function that will do the math for me:
“Dubvee, speaking, what’s the value?”
I tell it “4”. It has its own integer, which it calls it Narco. Narco takes on the value that I passed, so now Narco equals 4, just like Nicky. It doesn’t really matter to me what the function calls its own integer. It could have called it Nicky, too. I never see Narco, and Dubvee never sees Nicky. “Ok,” it says “I’ll get right back to you.”
Dubvee is a value returning function which takes its variable by value. This is how Dubvee would be declared in C++:
int Dubvee (int Narco);
And this is how Dubvee might be defined:
int Dubvee (int Narco) {
Narco = Narco * 2;
return Narco;
}
Dubvee does the math, calls me back, and says, “8”.
There’s a couple of things I can do with this 8. I could just say it out loud and forget about it. I could get another variable and assign it the value of 8, or I could assign Nicky the value of 8. Those three options are illustrated below in C++ syntax:
cout << Dubvee(Nicky) << endl; //I print the value of Nicky doubled, but I never store it
Mike=Dubvee(Nicky); //I assign Mike the value of Nicky doubled
Nicky=Dubvee(Nicky); //I double Nicky directly
By Reference.
Let’s say I don’t want to tell the function Nicky’s value. I want the function itself to find Nicky. Instead of telling Nicky’s value, I tell the function where Nicky is. I want a call by reference function.
“Dubre speaking, where’s your integer?” I give Dubre a number which represents Nicky’s location. For this blog post, we’ll call it Nicky’s address. Technically that’s not true, but it’s a good enough explanation. Dubre finds Nicky, using the address, and doubles it. Now Nicky equals 8. Dubre never told me “8”, it just did the work and left. Dubre would be declared as follows:
void Dubre(int & Naria);
and defined as follows:
void Dubre(int & Naria) {
Naria=Naria*2;
}
The ‘&’ symbol means that the function expects an address of an integer, not the value of that integer. Since Dubre doesn’t pass anything back to me, it’s declared with void, and there’s no return statement.
Similar to Dubvee, Dubre doesn’t need to use the same name that I use. The difference is, even though Dubre is using the name Naria, it’s refering directly to Nicky. Naria and Nicky are two names for the same integer.
This is how I double Nicky using Dubre:
Dubre ( Nicky);
Note the “&” symbol in the declaration and definition is not used in the call.
Dubvee is a void function, AKA a procedure, which takes its parameter by reference. Since there’s no return value, I can’t make an assignment like “Nicky=Dubre ( Nicky );” or “cout << Dubre (Nicky);".
What may be confusing at this point is, even though I passed an address, the name Naria refers to the variable at that location. So if Dubre doubled Naria with "Naria = Naria * 2;", it's doubled Nicky, not Nicky's location. In C++, that rule applies to function parameters. If you see the "&" symbol used differently, then different rules apply.
A function that uses reference parameters can return a value, and a function that uses value parameters doesn’t have to.
When I pass by value, my original variable is never touched by the function. It gets the value of the variable and makes a copy. Because it never gets the original variable. It's usually not the most efficient way but it's easier and safer to code functions that take parameters by value.
When I pass by reference, I'm giving the function direct access to the variable. This can be dangerous, but it's more efficient because they don't have to make a copy of the variable. Remember, variables aren't always integers; they can be very large and complex.