codingstuff.io
ExploreTutorialsProblemsCS Subjects
Get Started
ExploreTutorialsProblemsCS Subjects
Get Started
codingstuff.io

Master the art of building software through interactive tutorials, real-world problems, and guided projects.

Pune, Maharashtra, India

codingstuffmail@gmail.com

Product

  • Explore
  • Tutorials
  • Problems
  • CS Subjects

Company

  • About
  • Contact
  • Privacy Policy
  • Terms & Conditions
  • Sitemap

© 2026 codingstuff.io. All rights reserved.

Built with ❤️ for developers everywhere

/
/
All Tutorials
⚡

C++ Programming

36 / 87 topics
33Pointers34Pointers and Arrays35References36Call by Reference (Using Pointers)37Memory Management: new and delete
Tutorials/C++ Programming/Call by Reference (Using Pointers)
⚡C++ Programming

Call by Reference (Using Pointers)

Updated 2026-05-12
30 min read

Call by Reference (Using Pointers)

In this tutorial, you'll learn how to pass arguments by reference using pointers in C++. Understanding call by reference is crucial for modifying variables directly within functions and managing memory efficiently. We'll explore the mechanics of passing by pointer, a swap function example, common pitfalls, and compare pointers with reference parameters.

Introduction

Passing by reference allows functions to modify the original variables directly without creating copies. In C++, this can be achieved using pointers, which store the memory addresses of variables. Understanding how pointers work is essential for effective memory management and efficient code execution.

Passing Arguments by Pointer

When you pass a variable by pointer, you pass the address of that variable to the function. Inside the function, you use the dereference operator (*) to access and modify the original variable.

Example: Basic Pointer Usage

Let's start with a simple example where we pass an integer by pointer and modify it inside a function.

pass_by_pointer.cpp
1#include <iostream>
2
3void increment(int* ptr) {
4 *ptr = *ptr + 1;
5}
6
7int main() {
8 int num = 5;
9 std::cout << "Before increment: " << num << std::endl;
10 increment(&num);
11 std::cout << "After increment: " << num << std::endl;
12 return 0;
13}
Output
Before increment: 5
After increment: 6

In this example, the increment function takes a pointer to an integer (int* ptr). The address of num is passed using the & operator. Inside the function, we dereference the pointer with *ptr to modify the original variable.

Swap Function Example

A classic use case for passing by reference is implementing a swap function that exchanges the values of two variables.

Example: Swap Function

Here's how you can implement a swap function using pointers:

swap_function.cpp
1#include <iostream>
2
3void swap(int* a, int* b) {
4 int temp = *a;
5 *a = *b;
6 *b = temp;
7}
8
9int main() {
10 int x = 10, y = 20;
11 std::cout << "Before swap: x = " << x << ", y = " << y << std::endl;
12 swap(&x, &y);
13 std::cout << "After swap: x = " << x << ", y = " << y << std::endl;
14 return 0;
15}
Output
Before swap: x = 10, y = 20
After swap: x = 20, y = 10

In this example, the swap function takes two pointers to integers. It swaps the values of the variables pointed to by these pointers.

Modifying Caller Variables

Passing by pointer allows functions to modify the original variables directly. This is particularly useful when you need to update multiple variables or return more than one value from a function.

Example: Updating Multiple Variables

Here's an example where we update multiple variables using pointers:

update_variables.cpp
1#include <iostream>
2
3void updateValues(int* x, int* y) {
4 *x = 100;
5 *y = 200;
6}
7
8int main() {
9 int a = 50, b = 75;
10 std::cout << "Before update: a = " << a << ", b = " << b << std::endl;
11 updateValues(&a, &b);
12 std::cout << "After update: a = " << a << ", b = " << b << std::endl;
13 return 0;
14}
Output
Before update: a = 50, b = 75
After update: a = 100, b = 200

In this example, the updateValues function modifies the values of a and b directly using pointers.

Pointer vs Reference Parameters

While both pointers and references allow you to pass variables by reference, they have some differences:

FeaturePointersReferences
SyntaxUse * for dereferencingAutomatic dereferencing
NullabilityCan be nullptrAlways refers to a valid object
ReassignabilityCan point to different variablesCannot be reassigned
Memory ManagementMore control over memory allocation/deletionManaged automatically by the compiler

Example: Pointer vs Reference

Here's an example that demonstrates the differences between pointers and references:

pointer_vs_reference.cpp
1#include <iostream>
2
3void modifyPointer(int* ptr) {
4 ptr = new int(100); // Points to a new memory location
5}
6
7void modifyReference(int& ref) {
8 ref = 200; // Modifies the original variable
9}
10
11int main() {
12 int num = 50;
13 int* p = &num;
14 std::cout << "Before modifying pointer: *p = " << *p << std::endl;
15 modifyPointer(p);
16 std::cout << "After modifying pointer: *p = " << *p << std::endl;
17
18 std::cout << "Before modifying reference: num = " << num << std::endl;
19 modifyReference(num);
20 std::cout << "After modifying reference: num = " << num << std::endl;
21
22 delete p; // Clean up dynamically allocated memory
23 return 0;
24}
Output
Before modifying pointer: *p = 50
After modifying pointer: *p = 50
Before modifying reference: num = 50
After modifying reference: num = 200

In this example, modifyPointer changes the pointer to point to a new memory location, but it doesn't affect the original variable. On the other hand, modifyReference directly modifies the original variable.

Common Pitfalls

  1. Dangling Pointers: Always ensure that pointers are properly initialized and not left pointing to invalid memory locations.
  2. Memory Leaks: When using dynamic memory allocation (new), always remember to deallocate memory using delete.
  3. Null Pointer Dereferencing: Avoid dereferencing null pointers, as it leads to undefined behavior.

Practical Example: Dynamic Array Management

Let's put our knowledge of pointers and call by reference into practice with a simple program that manages a dynamic array.

Example: Managing a Dynamic Array

Here's an example where we create a dynamic array, modify its elements using pointers, and clean up the allocated memory:

dynamic_array.cpp
1#include <iostream>
2
3void initializeArray(int* arr, int size) {
4 for (int i = 0; i < size; ++i) {
5 arr[i] = i * 10;
6 }
7}
8
9void printArray(const int* arr, int size) {
10 for (int i = 0; i < size; ++i) {
11 std::cout << arr[i] << " ";
12 }
13 std::cout << std::endl;
14}
15
16int main() {
17 int size = 5;
18 int* myArray = new int[size];
19
20 initializeArray(myArray, size);
21 std::cout << "Initialized array: ";
22 printArray(myArray, size);
23
24 delete[] myArray; // Clean up the allocated memory
25 return 0;
26}
Output
Initialized array: 0 10 20 30 40

In this example, we dynamically allocate an integer array using new. The initializeArray function initializes the elements of the array, and the printArray function prints them. Finally, we clean up the allocated memory using delete[].

Summary

  • Pass by pointer allows functions to modify original variables directly.
  • Pointers provide more control over memory allocation and deallocation.
  • References are safer and easier to use but less flexible than pointers.
  • Always be cautious of dangling pointers and memory leaks.

What's Next?

In the next tutorial, we'll explore advanced memory management techniques using new and delete. Understanding these concepts will help you write more efficient and robust C++ programs. Stay tuned!


PreviousReferencesNext Memory Management: new and delete

Recommended Gear

ReferencesMemory Management: new and delete