Double Pointers : Pointer To Pointers In C++

Introduction to Pointer to Pointers:

Pointer to pointers, also known as double pointers, is a concept in C++ where a pointer variable holds the address of another pointer variable. This concept allows you to indirectly access a memory location that contains the address of another memory location. Pointer to pointers is particularly useful in scenarios where you need to dynamically allocate memory for multi-dimensional arrays, linked lists, or trees.

Key Points:

  1. Two Levels of Indirection:
    • Pointer to pointers introduces two levels of indirection. The first level points to the memory address, while the second level points to the value stored at that address.
  2. Dynamic Memory Allocation:
    • Pointer to pointers is commonly used in dynamic memory allocation scenarios where you need to allocate memory for an array of pointers, each pointing to dynamically allocated memory.
  3. Passing Arguments to Functions:
    • Pointer to pointers can be passed as arguments to functions, allowing the function to modify the original pointer variable.
  4. Error Handling:
    • Pointer to pointers can help in error handling situations where functions return a pointer to a pointer to indicate success or failure.

Example C++ Program:

Here’s an example program that demonstrates the usage of pointer to pointers with line-by-line explanations:

#include <iostream>
using namespace std;

// Function to allocate memory for a 2D array using pointer to pointers
int** allocateMemory(int rows, int cols) {
    int **arr = new int*[rows]; // Allocate memory for array of pointers
    for (int i = 0; i < rows; ++i) {
        arr[i] = new int[cols]; // Allocate memory for each row
    }
    return arr; // Return pointer to pointer
}

int main() {
    int rows = 3, cols = 2;
    
    // Allocate memory for a 2D array
    int **matrix = allocateMemory(rows, cols);
    
    // Initialize values
    int value = 1;
    for (int i = 0; i < rows; ++i) {
        for (int j = 0; j < cols; ++j) {
            matrix[i][j] = value++;
        }
    }
    
    // Print the 2D array
    cout << "Matrix:" << endl;
    for (int i = 0; i < rows; ++i) {
        for (int j = 0; j < cols; ++j) {
            cout << matrix[i][j] << " ";
        }
        cout << endl;
    }
    
    // Deallocate memory
    for (int i = 0; i < rows; ++i) {
        delete[] matrix[i]; // Deallocate memory for each row
    }
    delete[] matrix; // Deallocate memory for array of pointers

    return 0;
}

Explanation:

  1. allocateMemory Function:
    • The allocateMemory function dynamically allocates memory for a 2D array of integers using pointer to pointers.
    • It takes the number of rows and columns as parameters.
    • Inside the function, memory is first allocated for an array of pointers (arr) to hold the rows.
    • Then, memory is allocated for each row individually using a loop.
  2. main Function:
    • In the main function, define variables rows and cols to specify the dimensions of the 2D array.
    • Call the allocateMemory function to allocate memory for the 2D array.
    • Initialize the values of the 2D array in a sequential manner.
    • Print the contents of the 2D array using nested loops.
    • Deallocate the dynamically allocated memory for both the rows and the array of pointers using delete[].

This example demonstrates how pointer to pointers can be used to dynamically allocate memory for a 2D array and manipulate its contents efficiently in C++.

Given below are few more example programs to demonstrate pointer to pointers in C++

Pointer to Pointer – Swap Two Numbers

Introduction: This program demonstrates the usage of a pointer to a pointer to swap two numbers.

#include <iostream>

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

int main() {
    int x = 5, y = 10;
    int *ptr_x = &x;
    int *ptr_y = &y;

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

    return 0;
}

Explanation:

  • void swap(int **a, int **b): Defines a function swap that takes two pointer-to-pointer arguments.
  • int *temp = *a; *a = *b; *b = temp;: Swaps the values of the pointers a and b.
  • int *ptr_x = &x; int *ptr_y = &y;: Declares two pointer variables and assigns their addresses to x and y.
  • swap(&ptr_x, &ptr_y);: Calls the swap function with the addresses of ptr_x and ptr_y to swap their values.

This program demonstrates the usage of a pointer to a pointer to swap two numbers.

Pointer to Pointer – Find Maximum Element in Array

Introduction: This program demonstrates the usage of a pointer to a pointer to find the maximum element in an array.

#include <iostream>

int findMax(int **arr, int rows, int cols) {
    int max = **arr;
    for (int i = 0; i < rows; ++i) {
        for (int j = 0; j < cols; ++j) {
            if (*(*(arr + i) + j) > max) {
                max = *(*(arr + i) + j);
            }
        }
    }
    return max;
}

int main() {
    const int rows = 3, cols = 3;
    int arr[rows][cols] = {{1, 2, 3},
                           {4, 5, 6},
                           {7, 8, 9}};
    int *ptr = &arr[0][0];

    std::cout << "Maximum element in the array: " << findMax((int **)&ptr, rows, cols) << std::endl;

    return 0;
}

Explanation:

  • int findMax(int **arr, int rows, int cols): Defines a function findMax that takes a pointer to a pointer, representing a 2D array, and its dimensions.
  • int max = **arr;: Initializes max with the value of the first element of the array.
  • Nested loops iterate over the array elements, comparing each element with the current maximum and updating max if necessary.
  • int *ptr = &arr[0][0];: Declares a pointer ptr and assigns it to the address of the first element of the array.
  • findMax((int **)&ptr, rows, cols): Calls the findMax function with a type-casted pointer to pointer ptr to find the maximum element in the array.

This program demonstrates the usage of a pointer to a pointer to find the maximum element in an array.

Pointer to Pointer – Swap Two Strings

Introduction: This program demonstrates the usage of a pointer to a pointer to swap two strings.

#include <iostream>
#include <cstring>

void swapStrings(char **str1, char **str2) {
    char *temp = *str1;
    *str1 = *str2;
    *str2 = temp;
}

int main() {
    char *str1 = "Hello";
    char *str2 = "World";

    std::cout << "Before swapping: str1 = " << str1 << ", str2 = " << str2 << std::endl;
    swapStrings(&str1, &str2);
    std::cout << "After swapping: str1 = " << str1 << ", str2 = " << str2 << std::endl;

    return 0;
}

Explanation:

  • void swapStrings(char **str1, char **str2): Defines a function swapStrings that takes two pointer-to-pointer arguments representing strings.
  • char *temp = *str1; *str1 = *str2; *str2 = temp;: Swaps the pointers str1 and str2.
  • char *str1 = "Hello"; char *str2 = "World";: Declares two string pointers and initializes them with string literals.
  • swapStrings(&str1, &str2);: Calls the swapStrings function with the addresses of str1 and str2 to swap their values.

This program demonstrates the usage of a pointer to a pointer to swap two strings.

Pointer to Pointer – Dynamic Memory Allocation for 2D Array

Introduction: This program demonstrates the usage of a pointer to a pointer for dynamic memory allocation of a 2D array.

#include <iostream>

int main() {
    const int rows = 3, cols = 3;

    // Dynamic memory allocation for a 2D array
    int **arr = new int*[rows];
    for (int i = 0; i < rows; ++i) {
        arr[i] = new int[cols];
    }

    // Initialize the array
    int count = 1;
    for (int i = 0; i < rows; ++i) {
        for (int j = 0; j < cols; ++j) {
            arr[i][j] = count++;
        }
    }

    // Print the array
    std::cout << "2D Array:" << std::endl;
    for (int i = 0; i < rows; ++i) {
        for (int j = 0; j < cols; ++j) {
            std::cout << arr[i][j] << " ";
        }
        std::cout << std::endl;
    }

    // Deallocate memory
    for (int i = 0; i < rows; ++i) {
        delete[] arr[i];
    }
    delete[] arr;

    return 0;
}

Explanation:

  • Dynamic memory allocation for a 2D array:
    • int **arr = new int*[rows];: Allocates memory for an array of row pointers.
    • arr[i] = new int[cols];: Allocates memory for each row of the 2D array.
  • Initializes the array with sequential values.
  • Prints the 2D array.
  • Deallocates the dynamically allocated memory for the 2D array.

This program demonstrates the usage of a pointer to a pointer for dynamic memory allocation of a 2D array.

Pointer to Pointer – Function to Allocate Memory

Introduction: This program demonstrates the usage of a pointer to a pointer in a function to allocate memory for an integer array.

#include <iostream>

void allocateMemory(int **ptr, int size) {
    *ptr = new int[size];
}

int main() {
    int *arr;
    const int size = 5;

    allocateMemory(&arr, size);

    std::cout << "Memory allocated successfully!" << std::endl;

    delete[] arr; // Deallocate memory

    return 0;
}

Explanation:

  • void allocateMemory(int **ptr, int size): Defines a function allocateMemory that takes a pointer to a pointer ptr and an integer size.
  • *ptr = new int[size];: Allocates memory for an integer array of size size and assigns the address of the allocated memory to ptr.
  • allocateMemory(&arr, size);: Calls the allocateMemory function with the address of the pointer arr and the size of the array.
  • Deallocates the dynamically allocated memory for the integer array after use.

This program demonstrates the usage of a pointer to a pointer in a function to allocate memory for an integer array.

These examples provide a detailed understanding of pointers to pointers in C++