Contents

Arrays

Arrays in C++

In C++, an array is a collection of elements of the same data type, stored in contiguous memory locations. It allows you to store multiple values in a single variable and access them using an index. The size of the array must be specified at the time of declaration, and it cannot be changed later

Declaring and Initializing Arrays

Here’s how to declare and initialize arrays in C++:

1. Single-dimensional Array: This is the simplest form of an array.

Example:

				
					#include <iostream>
using namespace std;

int main() {
    // Declare and initialize a single-dimensional array
    int numbers[5] = {1, 2, 3, 4, 5};

    // Access and print array elements
    for (int i = 0; i < 5; i++) {
        cout << "Element at index " << i << ": " << numbers[i] << endl;
    }

    return 0;
}

				
			

Output:

				
					Element at index 0: 1
Element at index 1: 2
Element at index 2: 3
Element at index 3: 4
Element at index 4: 5

				
			

2. Multi-dimensional Array: Arrays can have more than one dimension. A two-dimensional array is commonly used to represent matrices.

				
					#include <iostream>
using namespace std;

int main() {
    // Declare and initialize a two-dimensional array
    int matrix[2][3] = {{1, 2, 3}, {4, 5, 6}};

    // Access and print array elements
    for (int i = 0; i < 2; i++) {
        for (int j = 0; j < 3; j++) {
            cout << "Element at [" << i << "][" << j << "]: " << matrix[i][j] << endl;
        }
    }

    return 0;
}

				
			

Output:

				
					Element at [0][0]: 1
Element at [0][1]: 2
Element at [0][2]: 3
Element at [1][0]: 4
Element at [1][1]: 5
Element at [1][2]: 6

				
			
Important Points about Arrays in C++:
  • Indexing: Array indexing starts from 0. The first element is accessed using index 0, the second with index 1, and so on.
  • Size Limitation: The size of the array must be a constant expression and cannot be modified after declaration.
  • Memory Management: The size of the array affects memory usage. For large data sets, dynamic arrays (using new keyword) or std::vector from the STL (Standard Template Library) can be used for flexibility.
Dynamic Arrays

If you need to create an array whose size can be determined at runtime, you can use dynamic memory allocation.

Example:

				
					#include <iostream>
using namespace std;

int main() {
    int size;
    cout << "Enter the size of the array: ";
    cin >> size;

    // Dynamically allocate an array
    int* dynamicArray = new int[size];

    // Initialize array elements
    for (int i = 0; i < size; i++) {
        dynamicArray[i] = i * 2;  // Assigning values
    }

    // Print the array elements
    for (int i = 0; i < size; i++) {
        cout << "Element at index " << i << ": " << dynamicArray[i] << endl;
    }

    // Free the allocated memory
    delete[] dynamicArray;

    return 0;
}

				
			

Output:

				
					Enter the size of the array: 5
Element at index 0: 0
Element at index 1: 2
Element at index 2: 4
Element at index 3: 6
Element at index 4: 8

				
			

But we can have array of void pointers and function pointers. The below program works fine.

				
					int main()
{
    void *arr[200];
}
				
			

How to print size of array parameter in C++?

In C++, calculating the size of an array can be misleading when done within functions. Here’s an example that illustrates this issue.

				
					// A C++ program demonstrating the incorrect method 
// of computing the size of an array passed to a function
#include <iostream>
using namespace std;

void checkSize(int arr[]) 
{ 
    cout << sizeof(arr) << endl; 
}

int main()
{
    int a[10];
    cout << sizeof(a) << " ";
    checkSize(a);
    return 0;
}

				
			

Output:

				
					40 8

				
			

Time Complexity: O(1)
Auxiliary Space: O(n) (where n is the array size)

In the output, the first cout statement in main() displays 40, while the second in checkSize() shows 8. The difference arises because arrays are passed as pointers to functions. Thus, both checkSize(int arr[]) and checkSize(int *arr) are equivalent. The output inside checkSize() reflects the size of a pointer, not the array.

				
					// A C++ program demonstrating how to use a reference 
// to find the size of an array
#include <iostream>
using namespace std;

void checkSize(int (&arr)[10])
{
    cout << sizeof(arr) << endl;
}

int main()
{
    int a[10];
    cout << sizeof(a) << " ";
    checkSize(a);
    return 0;
}

				
			

Output:

				
					40 40

				
			

Time Complexity: O(1)
Space Complexity: O(n) (where n is the array size)

Making a Generic Function

Example:

				
					// A C++ program to demonstrate how to use templates 
// and references to find the size of an array of any type
#include <iostream>
using namespace std;

template <typename T, size_t n>
void checkSize(T (&arr)[n])
{
    cout << sizeof(T) * n << endl;
}

int main()
{
    int a[10];
    cout << sizeof(a) << " ";
    checkSize(a);
 
    float f[20];
    cout << sizeof(f) << " ";
    checkSize(f);
    return 0;
}

				
			

Output:

				
					40 40
80 80

				
			

Time Complexity: O(1)
Space Complexity: O(n) (where n is the array size)

Determining the Size of a Dynamically Allocated Array

The next step involves printing the size of a dynamically allocated array. Here’s a hint to get you started:

				
					#include <iostream>
#include <cstdlib>
using namespace std;

int main()
{
    int *arr = (int*)malloc(sizeof(int) * 20);
    // Note: You need to keep track of the size since sizeof will not work here
    return 0;
}

				
			

In this case, since malloc returns a pointer, you cannot directly determine the size of the allocated memory using sizeof.

What is Array Decay in C++?

Array decay refers to the loss of both type and dimensions of an array, which typically occurs when an array is passed to a function by value or pointer. In this process, the first address of the array is sent, treating it as a pointer. As a result, the size reported is that of the pointer, not the actual size of the array in memory.

				
					// C++ code to demonstrate array decay
#include <iostream>
using namespace std;

// Function demonstrating Array Decay
// by passing array as a pointer
void demonstrateArrayDecay(int* p)
{
    // Displaying the size of the pointer
    cout << "Size of the array when passed by value: ";
    cout << sizeof(p) << endl;
}

int main()
{
    int a[7] = {1, 2, 3, 4, 5, 6, 7};

    // Displaying the original size of the array
    cout << "Actual size of array is: ";
    cout << sizeof(a) << endl;

    // Passing the array to the function
    demonstrateArrayDecay(a);

    return 0;
}

				
			

Output:

				
					Actual size of array is: 28
Size of the array when passed by value: 8

				
			
How to Prevent Array Decay?

One common approach to address array decay is to pass the size of the array as a separate parameter and to avoid using sizeof with array parameters. Another effective method is to pass the array by reference, which prevents the conversion of the array into a pointer and thus avoids decay.

				
					// C++ code to demonstrate prevention of array decay
#include <iostream>
using namespace std;

// Function that prevents array decay
// by passing the array by reference
void preventArrayDecay(int (&p)[7])
{
    // Displaying the size of the array
    cout << "Size of the array when passed by reference: ";
    cout << sizeof(p) << endl;
}

int main()
{
    int a[7] = {1, 2, 3, 4, 5, 6, 7};

    // Displaying the original size of the array
    cout << "Actual size of array is: ";
    cout << sizeof(a) << endl;

    // Calling the function by reference
    preventArrayDecay(a);

    return 0;
}

				
			

Output:

				
					Actual size of array is: 28
Size of the array when passed by reference: 28

				
			

Preserving array size by passing a pointer to the array:

Another way to maintain the size is by passing a pointer to the array, which includes an extra dimension compared to the original array.

				
					#include <iostream>
using namespace std;

// Function to demonstrate Array Decay with a pointer
void pDecay(int (*p)[7]) {
    // Display the size of the pointer to the array
    cout << "Size of array when passing a pointer: ";
    cout << sizeof(p) << endl;
}

int main() {
    int a[7] = {1, 2, 3, 4, 5, 6, 7};

    // Display original size of the array
    cout << "Original size of array: ";
    cout << sizeof(a) << endl;

    // Passing a pointer to the array
    pDecay(&a);

    return 0;
}

				
			

Output:

				
					Original size of array: 28
Size of array when passing a pointer: 8