Back to C++
2026-05-096 min read

Pass By Reference (C++)

Learn Pass By Reference (C++) step by step with clear examples and exercises.

Why This Matters

Welcome to this full guide on Pass By Reference in C++! Understanding pass by reference is essential for writing efficient code, managing memory effectively, and demonstrating a strong grasp of C++ fundamentals. This tutorial will help you tackle real-world coding challenges, prepare for interviews, and debug common mistakes. Let's look at deeper into the world of pass by reference!

Why This Matters

Pass by reference plays a crucial role in C++ programming as it allows functions to manipulate original data instead of creating copies. This can significantly improve program performance, reduce memory usage, and make your code more intuitive. In interviews, being familiar with pass by reference is often expected, so let's dive into the details!

The Importance of Pass By Reference

  • Improves program performance: Pass by reference eliminates the need for copying large objects, reducing the time complexity of function calls.
  • Reduces memory usage: By avoiding unnecessary copies, pass by reference helps conserve memory resources.
  • Makes code more intuitive: Pass by reference allows functions to directly manipulate original data, making the intention and behavior of your code clearer.

Prerequisites

Before proceeding, ensure you have a solid understanding of the following concepts:

  • Basic C++ syntax (variables, data types, operators)
  • Functions in C++
  • Pass by value and call by value semantics
  • Pointers in C++
  • Understanding of arrays and their properties

Core Concept

Pass by reference is a mechanism that enables functions to directly manipulate the original data passed as an argument. This is achieved by passing the memory address (pointer) of the variable instead of its actual value. In C++, this can be done using references.

Declaring and Initializing References

To declare a reference, we use the & symbol followed by the variable name:

int originalValue = 10;
int &reference = originalValue; // 'reference' is a reference to 'originalValue'

In this example, reference is a reference to originalValue. Any changes made to reference will also affect the original variable.

Passing Arguments by Reference

To pass an argument by reference in function calls, we use the & symbol before the formal parameter:

void incrementByReference(int &value) {
value++; // Incrementing 'value' directly affects the original variable
}

int main() {
int originalValue = 10;
incrementByReference(originalValue); // Passing 'originalValue' by reference
std::cout << originalValue << std::endl; // Output: 11
return 0;
}

In this example, the incrementByReference() function takes an integer reference as its argument. When we call this function with originalValue, any changes made to the formal parameter (value) will affect the original variable in the main() function.

Passing Arrays by Reference

When you pass an array by reference, the entire array (including all elements) is passed to the function:

void printArray(int arr[], int size) {
for (int i = 0; i < size; ++i) {
std::cout << arr[i] << " "; // Printing each element in 'arr' directly affects the original array
}
}

int main() {
int arr[] = {1, 2, 3};
int size = sizeof(arr) / sizeof(arr[0]);
printArray(arr, size); // Passing 'arr' by reference
return 0;
}

In this example, the printArray() function takes an array and its size as arguments. When we call this function with arr, any changes made to the formal parameter (arr) will affect the original array in the main() function.

Worked Example

Let's create a simple program that uses pass by reference to implement a swap function:

void swap(int &a, int &b) {
int temp = a;
a = b;
b = temp;
}

int main() {
int x = 5;
int y = 10;

std::cout << "Before swapping: x = " << x << ", y = " << y << std::endl;
swap(x, y);
std::cout << "After swapping: x = " << x << ", y = " << y << std::endl;

return 0;
}

In this example, the swap() function takes two integer references as its arguments and performs a swap operation. When we call this function with x and y, any changes made to the formal parameters (a and b) will affect the original variables in the main() function.

Common Mistakes

  1. Forgetting the & symbol when declaring references: If you forget to use the & symbol when declaring a reference, you'll end up with an error:
int originalValue = 10;
int reference = originalValue; // Error: 'reference' is not a reference
  1. Passing values instead of references: If you pass the value instead of the reference in function calls, any changes made to the formal parameter will create a new local variable and not affect the original data:
void increment(int value) {
value++; // Creates a new local variable 'value' and does not affect the original variable
}

int main() {
int originalValue = 10;
increment(originalValue); // Passing 'originalValue' by value
std::cout << originalValue << std::endl; // Output: 10
return 0;
}
  1. Using uninitialized references: If you use an uninitialized reference, you'll end up with a garbage value:
int &uninitializedReference; // 'uninitializedReference' is not initialized
std::cout << uninitializedReference << std::endl; // Outputs garbage value
  1. Returning references from functions: Be careful when returning references from functions, as this can lead to undefined behavior if the original object is destroyed before the function returns:
int &getReference() {
static int reference; // 'reference' is a static variable with global scope
return reference;
}

int main() {
getReference(); // Returns a reference to a static variable
std::cout << getReference() << std::endl; // Outputs the value of the static variable
return 0;
}
  1. Returning references to local variables: Returning references to local variables is also problematic, as these variables are destroyed when the function returns:
int getLocalReference() {
int localVariable = 10; // 'localVariable' is a local variable with automatic storage duration
return localVariable; // Returns a reference to a local variable that will be destroyed after the function returns
}

int main() {
int &reference = getLocalReference(); // 'reference' is a reference to a local variable
std::cout << reference << std::endl; // Outputs garbage value, as 'localVariable' has been destroyed
return 0;
}

Practice Questions

  1. Write a function doubleAverage(int arr[], int size) that calculates the average of an array using pass by reference.
  2. Implement a function reverseArray(int arr[], int size) that reverses the order of elements in an array using pass by reference.
  3. Create a program that uses pass by reference to implement a function findMax(int arr1[], int size1, int arr2[], int size2) that returns the maximum of two arrays.
  4. Write a function getMaxMin(int arr[], int size, int &maxValue, int &minValue) that finds and returns both the maximum and minimum values in an array using pass by reference.
  5. Implement a function sortArray(int arr[], int size) that sorts an array in ascending order using pass by reference and the bubble sort algorithm.

FAQ

Why use pass by reference instead of pointers?

Pass by reference provides a cleaner and more intuitive syntax compared to using pointers. It eliminates the need for explicit memory allocation and deallocation, making it easier to write and maintain code. Additionally, references offer constant-time access to the original data, while dereferencing a pointer incurs an additional indirection cost.

Can I pass objects by reference in C++?

Yes! In addition to primitive data types, you can also pass objects by reference in C++. To do this, simply declare a reference to the object type:

class MyClass {
public:
int value;
};

MyClass obj1, obj2;
MyClass &reference = obj1; // 'reference' is a reference to 'obj1'

What happens if I pass an array by reference to a function?

When you pass an array by reference, the entire array (including all elements) is passed to the function. This allows the function to manipulate all elements of the array directly:

void incrementArray(int arr[], int size) {
for (int i = 0; i < size; ++i) {
arr[i]++; // Incrementing each element in 'arr' directly affects the original array
}
}

int main() {
int arr[] = {1, 2, 3};
int size = sizeof(arr) / sizeof(arr[0]);
incrementArray(arr, size); // Passing 'arr' by reference
for (int i = 0; i < size; ++i) {
std::cout << arr[i] << " "; // Output: 2 3 4
}
return 0;
}
Pass By Reference (C++) | C++ | XQA Learn