C++ tutorials  /  Arrays in C++
Chapter 6 · C++

Arrays in C++

An array in C++ is a fixed-size, contiguous collection of elements of the same data type, stored in adjacent memory locations and accessed using a zero-based index. Once declared, an array's size cannot be changed, and each element can be directly accessed or modified in constant time O(1) using its index, since the compiler calculates the exact memory address of any element using the array's base address and the element's position.

Think of an array like a row of numbered lockers in a school hallway — each locker holds one item, all lockers are the same size, and they're all lined up right next to each other. To get to locker number 5, you don't have to check lockers 1 through 4 first — you can go straight there because you know exactly how far it is from the first locker. That's how arrays work: elements are stored back-to-back in memory, and the index lets the computer jump directly to any element instantly, which is why arrays are extremely fast for accessing data when you know the position you need.

A spreadsheet application stores each row of a column (like all the prices in an 'Amount' column) in an array-like structure for fast access and calculation. A leaderboard in a game like Call of Duty stores the top 10 players' scores in an array, iterating through it to render the rankings on screen. Image processing software represents a black-and-white image's pixel brightness values as a 2D array (rows and columns), where each cell holds one pixel's intensity, and applying a filter means looping through this 2D array and transforming each value. Weather forecasting systems store 24 hours of temperature readings in a simple 1D array, making it trivial to calculate the day's average, minimum, and maximum temperature by iterating through the fixed set of readings.

Without arrays, storing multiple related values of the same type (like 100 student scores) would require creating 100 separate individually-named variables, which is impractical to write, impossible to loop through programmatically, and doesn't scale to real-world data sizes. Arrays let programs store, access, and process large groups of related data efficiently using loops and indices, forming the foundation for more advanced data structures like matrices, strings (which are essentially char arrays), stacks, queues, and the building blocks used throughout the C++ Standard Template Library (STL).

  • One-Dimensional (1D) Arrays: The simplest form of array — a single row of elements of the same type, accessed with one index (e.g., 'scores[3]'), commonly used to store lists like student grades, temperature readings, or sales figures.
  • Two-Dimensional (2D) Arrays: An array of arrays, organized as rows and columns (like a table or matrix), accessed using two indices (e.g., 'matrix[row][col]'), commonly used to represent grids, game boards, images, and mathematical matrices.
  • Multi-Dimensional Arrays: Arrays with three or more dimensions (e.g., 'int cube[3][3][3]'), used for more complex data representations such as 3D spatial data, volumetric data, or storing multiple related 2D grids together.
  • Character Arrays (C-Style Strings): An array of 'char' elements terminated by a null character '\0', historically used in C and still supported in C++ to represent text, though modern C++ generally prefers the safer, more flexible 'std::string' class for string handling.
  • Dynamic Arrays (via std::vector or new[]): Unlike fixed-size built-in arrays, dynamic arrays can grow or shrink at runtime. In modern C++, 'std::vector' from the STL is the preferred way to get resizable array-like behavior with automatic memory management, though arrays can also be dynamically allocated manually using 'new[]' and 'delete[]'.
// 1D array declaration and initialization dataType arrayName[size]; dataType arrayName[size] = {value1, value2, value3}; dataType arrayName[] = {value1, value2, value3}; // size inferred // Accessing and modifying elements arrayName[index] = value; cout << arrayName[index]; // 2D array declaration and initialization dataType arrayName[rows][cols]; dataType arrayName[2][3] = { {1, 2, 3}, {4, 5, 6} }; // Accessing 2D array elements arrayName[row][col] = value;
A developer needs to store the test scores of 30 students to calculate the class average, find the highest score, and identify how many students passed — a task that would be impractical with 30 individually named variables — and additionally needs to represent a simple 3x3 tic-tac-toe game board where each cell can hold 'X', 'O', or be empty.
Storing and Processing Student Scores with a 1D Array
Demonstrates declaring, initializing, and looping through a 1D array to calculate the sum and average of stored values.
cpp
#include <iostream> using namespace std; int main() { int scores[5] = {78, 85, 92, 66, 74}; int sum = 0; for (int i = 0; i < 5; i++) { sum += scores[i]; } double average = sum / 5.0; cout << "Total: " << sum << endl; cout << "Average: " << average << endl; return 0; }
Total: 395 Average: 79
The array 'scores' is initialized with 5 fixed values. A for loop iterates from index 0 to 4, accessing each element via 'scores[i]' and adding it to 'sum'. Dividing by '5.0' (a double) ensures accurate floating-point division rather than truncated integer division for the average calculation.
Representing a Grid with a 2D Array
Shows how to declare, initialize, and traverse a 2D array using nested loops, simulating a simple 3x3 game board.
cpp
#include <iostream> using namespace std; int main() { char board[3][3] = { {'X', 'O', 'X'}, {'O', 'X', 'O'}, {'X', 'O', 'X'} }; for (int row = 0; row < 3; row++) { for (int col = 0; col < 3; col++) { cout << board[row][col] << " "; } cout << endl; } return 0; }
X O X O X O X O X
The 2D array 'board' is initialized as an array of 3 rows, each containing 3 characters. The outer loop iterates over each row, and the inner loop iterates over each column within that row, printing 'board[row][col]' to reconstruct the grid layout on the console, demonstrating the row-major traversal pattern typical of 2D array processing.
  • Off-by-One / Out-of-Bounds Array Access: Arrays in C++ use zero-based indexing, so an array of size 5 has valid indices 0 through 4 — accessing 'array[5]' is out of bounds. C++ does NOT automatically check array bounds at runtime, so this doesn't throw a clean error; instead it causes undefined behavior, potentially reading/writing garbage memory or corrupting other variables silently.
  • Assuming Arrays Know Their Own Size: Unlike some higher-level languages, a C++ array doesn't inherently 'know' its length once passed to a function — it decays into a pointer, losing size information. Beginners often forget this and pass an array to a function expecting to call something like 'array.length()', when instead the size must be passed separately as an extra parameter, or a container like 'std::vector' or 'std::array' should be used instead.
  • Uninitialized Array Elements Containing Garbage Values: Declaring 'int arr[5];' without initializing it leaves all elements containing unpredictable garbage values from whatever was previously in that memory, similar to uninitialized primitive variables. Always initialize arrays explicitly (e.g., 'int arr[5] = {0};' to zero-initialize all elements) if you plan to use them before assigning real values.
  • Confusing Array Size in Bytes with Number of Elements: Using 'sizeof(array)' returns the total size of the array in bytes, not the number of elements. To get the element count, developers must divide: 'sizeof(array) / sizeof(array[0])' — forgetting this and using 'sizeof(array)' directly as a loop bound causes the loop to run far more times than intended, reading out of bounds.
  • Trying to Resize a Fixed-Size Array: Once declared with a specific size (e.g., 'int arr[10];'), a built-in C++ array's size is fixed for its entire lifetime and cannot grow or shrink. Beginners attempting to add more elements than the declared size causes buffer overflow bugs; if dynamic resizing is needed, 'std::vector' should be used instead of a raw array.
  • Prefer std::vector or std::array Over Raw C-Style Arrays in Modern C++: 'std::vector' provides dynamic resizing, automatic memory management, and built-in bounds-checked access (via '.at()'), while 'std::array' provides a fixed-size array with a safer interface (like '.size()') and better integration with the STL — both are generally safer and more convenient than raw arrays for most modern C++ code, reserving raw arrays mainly for low-level or performance-critical scenarios.
  • Always Pass the Array Size Alongside the Array to Functions: Since raw arrays decay to pointers when passed to functions (losing size information), always pass the element count as a separate parameter, e.g., 'void processArray(int arr[], int size)', so the function knows the array's actual bounds and can safely iterate through it without guessing.
  • Initialize Arrays Explicitly to Avoid Garbage Values: Always initialize arrays at declaration, even if just to zero (e.g., 'int arr[10] = {0};'), rather than leaving elements uninitialized, to avoid unpredictable bugs caused by reading garbage memory before values are properly assigned.
  • Double-Check Loop Bounds Against Array Size, Especially in Nested Loops: When looping through arrays (especially 2D arrays with nested loops), carefully verify that loop conditions use '<' with the exact declared size (not '<=', which causes off-by-one overflow), and that row/column bounds in 2D array traversal match the array's actual declared dimensions.
What is the difference between an array and a std::vector in C++?
A built-in array has a fixed size determined at compile time (or allocation time for dynamic arrays) that cannot change during the program's execution, and provides no built-in bounds checking or size-tracking methods. 'std::vector', part of the STL, is a dynamic, resizable array-like container that automatically manages its own memory, can grow or shrink at runtime using methods like 'push_back()', and provides convenient member functions like '.size()' and bounds-checked access via '.at()', making it generally safer and more flexible for most modern C++ use cases.
Why doesn't accessing an out-of-bounds array index in C++ throw an error like it does in some other languages?
C++ prioritizes raw performance and gives programmers direct control over memory, so built-in arrays do not perform automatic bounds checking on every access — doing so would add runtime overhead to every single array operation. Accessing an out-of-bounds index results in undefined behavior, meaning the program might crash, silently corrupt nearby memory, or appear to work correctly by chance, which is why careful manual bounds management (or using safer alternatives like 'std::vector::at()', which does throw an exception) is critical in C++.
Explain how a 2D array is stored in memory in C++.
A 2D array in C++ is stored in row-major order, meaning all elements of the first row are stored contiguously in memory, immediately followed by all elements of the second row, and so on. This means that even though we conceptually think of a 2D array as a grid, it is physically a single contiguous 1D block of memory, and the compiler calculates the memory address of 'array[row][col]' using the formula 'baseAddress + (row * numberOfColumns + col) * sizeOfElement'.
What happens when an array is passed as an argument to a function in C++?
When a built-in array is passed to a function, it 'decays' into a pointer to its first element rather than being copied in its entirety — this means the function only receives the array's starting memory address, not its size, so any 'sizeof' calculation performed inside the function on the parameter would return the size of a pointer, not the original array. This is why the array's size must always be passed as a separate explicit parameter alongside the array itself.
What is the time complexity of accessing an element in an array by index, and why?
Accessing an array element by index is O(1) — constant time — because arrays are stored in contiguous memory, and the exact memory address of any element can be calculated directly using the formula 'baseAddress + (index * sizeOfElement)', without needing to traverse or search through preceding elements. This is a major advantage of arrays over structures like linked lists, where accessing an arbitrary element requires O(n) sequential traversal from the head.
Write a C++ program that finds and prints the largest and smallest elements in a given array of integers.
#include <iostream> using namespace std; int main() { int arr[6] = {45, 12, 89, 33, 7, 61}; int largest = arr[0], smallest = arr[0]; for (int i = 1; i < 6; i++) { if (arr[i] > largest) largest = arr[i]; if (arr[i] < smallest) smallest = arr[i]; } cout << "Largest: " << largest << endl; cout << "Smallest: " << smallest << endl; return 0; }
Write a program that reverses the elements of an array in place without using an extra array.
#include <iostream> using namespace std; int main() { int arr[5] = {1, 2, 3, 4, 5}; int start = 0, end = 4; while (start < end) { int temp = arr[start]; arr[start] = arr[end]; arr[end] = temp; start++; end--; } for (int i = 0; i < 5; i++) { cout << arr[i] << " "; } return 0; }
Write a program that adds two 2x2 matrices (represented as 2D arrays) and prints the resulting matrix.
#include <iostream> using namespace std; int main() { int a[2][2] = {{1, 2}, {3, 4}}; int b[2][2] = {{5, 6}, {7, 8}}; int result[2][2]; for (int i = 0; i < 2; i++) { for (int j = 0; j < 2; j++) { result[i][j] = a[i][j] + b[i][j]; cout << result[i][j] << " "; } cout << endl; } return 0; }

Arrays are a fundamental data structure in C++ that store multiple elements of the same type in contiguous memory, enabling fast O(1) indexed access and efficient processing of large groups of related data via loops. Understanding the distinction between 1D and 2D arrays, how arrays decay to pointers when passed to functions, and the risks of out-of-bounds access (which C++ does not automatically guard against) is essential for writing safe, efficient code. While raw arrays remain foundational to understanding memory layout, modern C++ development often favors safer, more flexible alternatives like 'std::vector' and 'std::array' for everyday use.

© 2026 CompileX. Maintained by Aditya Kumar Sharma.