Passing by value vs Passing by reference in C++

The concept of passing a variable to a function by value or by reference is somewhat confusing to beginners. It was difficult for me to comprehend until I learned the essential elements of a variable.

A variable is a named memory location that stores a value. However, there is more to this. A variable is composed of a rvalue (right value) and a lvalue (left value). The rvalue represents the value stored in the memory location. Whereas, the lvalue designates the address of the memory location.

When you pass a variable to a function, you either pass the variable's rvalue or lvalue. If you pass the rvalue to a function's argument, you are passing the variable by value. However, if you pass the variable's lvalue, you are passing the variable by reference. Passing a variable by reference equates to saying "passing its address to the function."

So what's the point of all of this? The point is this: Passing the address of a variable is the only way to have a function modify the content of a variable.

Let's talk about the differences between each method.

Difference in function declaration

Functions that receive a value through its argument are declared as:

int add(int a);

In practice, the function is use as follows:

int main(){

int myVariable=2; //1. define a variable
int myAnswer=add(myVariable); //2. pass the variable by value

return 0;
}

In line 1, you define a variable named 'myVariable.' In line 2, the variable is "passed by value" to the function 'add.'

In contrast, functions that receive an address through its argument are declared as:

int add(int *a);

The argument is declared as a pointer since pointers can receive addresses.

In practice, the function is use as follows:

int main(){

int myVariable=2; //1. define a variable
int myAnswer=add(&myVariable); //2. pass the variable by reference

return 0;
}

In line 1, you define a variable named 'myVariable.' However, in line 2, the variable is "passed by reference" to the function 'add.' The symbol '&' means "The address of."

Difference in function definition

There are differences in the function definition for each method. In a "pass by value" method, a function is defined as:

int add(int a){

int b=a+1; //1. increment the incoming value by 1

return b; //2. return the value of b
}

In the code snippet above, the function increments the value of 'a' by 1 (see line 1). Line 2, returns the value of b.

In a "pass by reference" method, a function is defined as:

int add(int *a){

int b=*a+1; //1. dereference the pointer and increment the value by 1

*a=5; //2. modify the value of the variable

return b; //3. return the value of b
}

Line 1 dereferences the pointer 'a.'; it accesses the value the pointer 'a' points. The value is then incremented by 1.

Line 2 modifies the value the pointer 'a' points to and sets it equal to 5. Line 3 returns the value of b.

Examples of each method

Let's go through a complete example of each method:

"Pass by value" method

In the code snippet below, lines 1 and 2 declare and define the function 'add.'

Line 5 shows the start of the 'main()' function. Line 6 defines a variable 'myVariable.' This variable is "passed by value" to the function 'add' in line 7.

Lines 8 and 9 prints the value of 'myAnswer' and 'myVariable.'

int add(int a); //1. declare a pass by value function

//2. define a pass by value function
int add(int a){

    int b=a+1; //3. increment the incoming value by 1

    return b; //4. return the value of b
}

//5. main function
int main() {

    int myVariable=2; //6. define a variable

    int myAnswer=add(myVariable); //7. pass the variable by value

    std::cout<<myAnswer<<std::endl; //8. print the value of myAnswer

    std::cout<<myVariable<<std::endl; //9. print the value of myVariable

    return 0;
}

When you run this program, the output of 'myAnswer' is 3, and 'myVariable' is 2. As expected, the function did not change the value of 'myVariable.'

"Pass by reference" method

In the code snippet below, lines 1 and 2 declare and define the function 'add.'

Line 6 shows the start of the 'main()' function. Line 7 defines a variable 'myVariable.' This variable is "passed by reference" to the function 'add' in line 8.

Lines 9 and 10 prints the value of 'myAnswer' and 'myVariable.'

int add(int *a); //1. declare a pass by reference function

//2. define a pass by reference function
int add(int *a){

    int b=*a+1; //3. dereference the pointer and increment the value by 1

    *a=5; //4. modify the value of the variable

    return b; //5. return the value of b
}

//6. main function
int main() {

    int myVariable=2; //7. define a variable

    int myAnswer=add(&myVariable); //8. pass the variable by reference

    std::cout<<myAnswer<<std::endl; //9. print the value of myAnswer

    std::cout<<myVariable<<std::endl; //10. print the value of myVariable

    return 0;
}

When you execute the program above, the output of 'myAnswer' is 3. However, 'myVariable' was modified and now equals 5.

The concept of "pass by value" vs. "pass by reference" may be difficult to grasp. In doubt always remember: "passing by reference" is the only way to have a function modify the content of a variable.

Hope this helps

Reference: C++ Pointers and Dynamic Memory Management

Harold Serrano

Computer Graphics Enthusiast. Currently developing a 3D Game Engine.