By Sneh and Manikandan Kurup
A two-dimensional array in C++ provides a powerful way to organize data into a grid-like table of rows and columns. This article will walk you through the fundamentals of declaring and initializing 2D arrays, including operations like handling user input and performing matrix addition. We will also dive into advanced topics such as dynamic arrays, pointers, performance optimization, and avoiding common errors. Let’s jump in!
Key takeaways:
for
loops for rows and columns.new[]
for variable sizing.std::vector<std::vector<int>>
is the recommended alternative as it automatically manages memory and is safer to use.A two-dimensional array, often called a 2D array or a matrix, is a fundamental data structure in C++. The following image depicts a two-dimensional array.
This structure allows you to store and access data in a tabular format, making it incredibly useful for a variety of programming tasks, from simple games to complex scientific computations.
While a one-dimensional array can be visualized as a single row of elements, a 2D array expands this by having multiple rows, each containing multiple columns of elements. All elements in a 2D array must be of the same data type.
In C++, you can initialize a two-dimensional array at the same time you declare it. The most common method is to use nested curly braces {}
to specify the values for each row.
You must always specify the size of the columns, though the row size can sometimes be inferred by the compiler from the initializer list.
int arr[4][2] = {
{1234, 56},
{1212, 33},
{1434, 80},
{1312, 78}
} ;
As you can see, we initialize a 2D array arr
, with 4 rows and 2 columns. It’s an array of arrays, where each element is itself an array of integers.
We can also initialize a 2D array in the following way.
int arr[4][2] = {1234, 56, 1212, 33, 1434, 80, 1312, 78};
In this case too, arr
is a 2D array with 4 rows and 2 columns. While this syntax is correct, it is generally considered less readable and can be prone to errors, especially for larger arrays. For better clarity and maintainability, it is highly recommended to use nested curly braces to visually separate the rows.
In the prvious section, we initialized a 2D array. But to verify that it was initialized correctly, we must print its contents. Displaying a 2D array in a readable, grid-like format is a common task. The fundamental idea is to iterate through each row and, for each row, iterate through each of its columns. This is typically achieved using nested loops.
Here’s how we can print a 2D array:
#include <iostream>
using namespace std;
int main() {
int arr[4][2] = {
{ 10, 11 },
{ 20, 21 },
{ 30, 31 },
{ 40, 41 }
};
int i, j;
cout << "Printing a 2D Array:\n";
for (i = 0; i < 4; i++) {
for (j = 0; j < 2; j++) {
cout << "\t" << arr[i][j];
}
cout << endl;
}
return 0;
}
In the above code:
arr[4][2]
.for
loops.for
loop iterates over the rows, while the inner loop iterates over the columns of the 2D array,i
), the inner loop (indexed by j
) traverses all columns of that specific row.arr[i][j]
, individually.Here’s the output:
Previously, we saw how to initialize a 2D array with predefined values. Now, let’s see how to populate an array using user input.
#include <iostream>
using namespace std;
int main() {
int s[2][2];
int i, j;
cout << "\n2D Array Input:\n";
for (i = 0; i < 2; i++) {
for (j = 0; j < 2; j++) {
cout << "\ns[" << i << "][" << j << "]= ";
cin >> s[i][j];
}
}
cout << "\nThe 2-D Array is:\n";
for (i = 0; i < 2; i++) {
for (j = 0; j < 2; j++) {
cout << "\t" << s[i][j];
}
cout << endl;
}
return 0;
}
In the code above, we declare a 2x2 2D array named s
. A pair of nested for
loops then traverses the array, prompting the user for input to populate each element. Finally, the completed array is printed to display the result.
Here’s the output:
Matrix addition is a fundamental operation in linear algebra where two matrices are added together to produce a third matrix. This operation is straightforward to implement in C++ using two-dimensional arrays. Let’s see an example:
#include <iostream>
using namespace std;
int main() {
int m1[5][5], m2[5][5], m3[5][5];
int i, j, r, c;
cout << "Enter the no.of rows of the matrices to be added(max 5):";
cin >> r;
cout << "Enter the no.of columns of the matrices to be added(max 5):";
cin >> c;
cout << "\n1st Matrix Input:\n";
for (i = 0; i < r; i++) {
for (j = 0; j < c; j++) {
cout << "\nmatrix1[" << i << "][" << j << "]= ";
cin >> m1[i][j];
}
}
cout << "\n2nd Matrix Input:\n";
for (i = 0; i < r; i++) {
for (j = 0; j < c; j++) {
cout << "\nmatrix2[" << i << "][" << j << "]= ";
cin >> m2[i][j];
}
}
cout << "\nAdding Matrices...\n";
for (i = 0; i < r; i++) {
for (j = 0; j < c; j++) {
m3[i][j] = m1[i][j] + m2[i][j];
}
}
cout << "\nThe resultant Matrix is:\n";
for (i = 0; i < r; i++) {
for (j = 0; j < c; j++) {
cout << "\t" << m3[i][j];
}
cout << endl;
}
return 0;
}
In the above code:
m1
and m2
will hold the user’s input, while m3
will store the final result. These arrays are initialized with a maximum size, such as 5x5.for
loops will iterate through each position in m1
and m2
and populate them with user-provided values.m3
) is calculated by summing the corresponding elements from the input matrices, as shown in this operation: m3[i][j] = m1[i][j] + m2[i][j]
m3
matrix, containing the results of the addition, is printed.The output is as follows:
Just as we can create pointers to integers, floats, and characters, we can also declare a pointer that references an entire array. The following program demonstrates how to implement and use this concept.
#include <iostream>
using namespace std;
int main() {
int s[5][2] = {
{1, 2},
{1, 2},
{1, 2},
{1, 2}
};
int (*p)[2];
int i, j;
for (i = 0; i <= 3; i++) {
p = &s[i];
cout << "Row" << i << ":";
for (j = 0; j <= 1; j++) {
cout << "\t" << *(*p + j);
}
cout << endl;
}
return 0;
}
The code above demonstrates how to traverse and print a 2D array using a pointer:
s[5][2]
, along with a pointer declared as int (*p)[2]
. This specific syntax defines p
as a pointer capable of storing the address of an array of 2 integers.s
is an array containing 5 elements, where each element is, in turn, an array of 2 integers.for
loop iterates through these 5 “rows.” In each step, we assign the address of the current row s[i]
to our pointer p
.p
now pointing to a specific row, the inner for
loop iterates through the columns of that row. The expression (*p + j)
calculates the memory address of the individual element s[i][j]
. By dereferencing this address with *(*p + j)
, we can access and print the element’s value.Here’s the print output:
In this section, we’ll learn how to pass a 2D array to a function and access its elements. The code below demonstrates this concept by passing an array, a
, to two different functions: show()
and print()
. Both functions perform the same action, which is to access and display the contents of the array they receive.
#include <iostream>
using namespace std;
void show(int (*q)[4], int row, int col) {
int i, j;
for (i = 0; i < row; i++) {
for (j = 0; j < col; j++) {
cout << "\t" << *(*(q + i) + j);
}
cout << "\n";
}
cout << "\n";
}
void print(int q[][4], int row, int col) {
int i, j;
for (i = 0; i < row; i++) {
for (j = 0; j < col; j++) {
cout << "\t" << q[i][j];
}
cout << "\n";
}
cout << "\n";
}
int main() {
int a[3][4] = { 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21 };
show(a, 3, 4);
print(a, 3, 4);
return 0;
}
Here:
show()
function, the parameter int (*q)[4]
acts like a special pointer designed to hold the location of a single row (which is an array of 4 integers) at a time.*(*(q + i) + j)
first points to the correct row (i
) and then finds the specific element (j
) within that row.print()
function uses a more familiar declaration, int q[][4]
, which allows you to access elements with the much simpler and more intuitive q[i][j]
notation.int q[][4]
syntax is just a convenient shortcut. Behind the scenes, the compiler treats it exactly the same as the pointer version, int (*q)[4]
.show()
function’s complex syntax is useful for demonstrating how pointers work “under the hood,” while print()
uses the simple syntax you would normally use in your code.The print output is as follows:
A dynamic 2D array is a 2D array whose dimensions (rows, columns, or both) are set during program execution. Instead of being allocated on the stack with a fixed size, it is allocated on the heap, a pool of memory available to the program at runtime. This is achieved using pointers and dynamic memory allocation with the new operator.
The most common C-style method for creating a dynamic 2D array is to create an “array of pointers.” Here’s how:
This creates a 2D structure where a primary pointer (int**
) points to an array of row pointers (int*
), and each row pointer points to the actual row data. Let’s walk through an example where a user specifies the number of rows and columns.
#include <iostream>
using namespace std;
int main() {
int rows, cols;
cout << "Enter number of rows: ";
cin >> rows;
cout << "Enter number of columns: ";
cin >> cols;
int** matrix;
matrix = new int*[rows];
for (int i = 0; i < rows; ++i) {
matrix[i] = new int[cols];
}
cout << "\nFilling the matrix with values (i + j)..." << endl;
for (int i = 0; i < rows; ++i) {
for (int j = 0; j < cols; ++j) {
matrix[i][j] = i + j; // Assign a value
cout << matrix[i][j] << "\t";
}
cout << endl;
}
cout << "\nDeallocating memory..." << endl;
for (int i = 0; i < rows; ++i) {
delete[] matrix[i]; // Use delete[] for arrays
}
delete[] matrix;
cout << "Memory deallocated successfully." << endl;
return 0;
}
Here:
int** matrix
), where the number of pointers is equal to the number of rows the user requested.i + j
) and printing the matrix to the console.While powerful, C-style dynamic arrays come with significant responsibilities and drawbacks:
delete[]
results in a memory leak, where your program holds onto memory it no longer needs, potentially causing it to crash or slow down the system.matrix[rows][cols]
). This leads to undefined behavior, which is a common source of bugs.When working with small 2D arrays, performance is rarely an issue. However, for large datasets, as seen in scientific computing, image processing, or data analysis, how you access and manipulate your array can have a massive impact on execution speed. Performance is often limited not by the CPU’s processing power but by the time it takes to fetch data from main memory (RAM).
The key to optimization lies in understanding and leveraging the CPU cache.
int**
method (an array of pointers) can scatter the rows across different memory locations. This can reduce cache efficiency when moving from the end of one row to the start of the next. For better performance, allocate the entire 2D array as a single, contiguous 1D block of memory of size ROWS * COLS
. This guarantees that all elements, regardless of row, are packed together, maximizing data locality and improving cache performance. You must then manually calculate the index for each element as [row * COLS + col]
.-O2
, -O3
for GCC/Clang or /O2
for Visual Studio) to get a significant, free performance boost.Working with 2D arrays can lead to several common bugs. Being aware of these pitfalls can help you write more robust and correct code.
0
to SIZE-1
range. Accessing an element like arr[ROWS]
results in undefined behavior, leading to data corruption or crashes. To avoid this, always use strict less-than (<
) comparisons in your loops, for example: for (int i = 0; i < ROWS; ++i)
.void func(int arr[][10])
. The best way to avoid this issue entirely is to use std::vector
.new[]
, failing to delete[]
every allocated block causes memory leaks. You must deallocate in the reverse order of allocation: first delete each row array, then delete the array of pointers. The safest way to prevent this is by using std::vector
or smart pointers, which manage memory automatically.arr[j][i]
instead of arr[i][j]
) can cause logical bugs or out-of-bounds errors. Using clear loop variable names like row and col instead of generic i
and j
makes your code more readable and helps prevent this mistake.You declare a 2D array by specifying its data type, a name, and the number of rows and columns in separate square brackets. The dimensions must be constant values known at compile time.
Syntax:
data_type array_name[NUMBER_OF_ROWS][NUMBER_OF_COLUMNS];
For example:
int matrix[3][4];
You can initialize a 2D array at the time of declaration using nested curly braces {}
. Each inner set of braces represents a row.
For example:
int matrix[3][4] = {
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12}
};
You can access an element by using the array name followed by the row and column index in square brackets. C++ uses zero-based indexing, so the first row and first column are at index 0.
Syntax:
array_name[row_index][column_index]
For example:
int value = matrix[1][2];
When passing a 2D array to a function, you must specify the size of the columns in the function’s parameter list. The number of rows is often passed as a separate argument.
The most common way is to leave the row dimension empty but specify the column dimension:
const int COLS = 4;
void displayMatrix(int arr[][COLS], int rows) {
// function body to print the array
}
The safest and most flexible method is to use a std::vector
of std::vectors
, which carries its own size information and can be passed by reference without these complex rules.
#include <vector>
void displayMatrix(const std::vector<std::vector<int>>& matrix) {
// function body to print the vector
}
In this article, we have explained two-dimensional arrays, covering static declaration, dynamic allocation, and practical operations like matrix addition. We explored the nuances of using pointers and passing arrays to functions, as well as critical performance considerations. Most importantly, we highlighted the common pitfalls of C-style arrays and contrasted them with the benefits of using modern C++ alternatives.
To continue expanding your knowledge of arrays in C++, here are a few useful tutorials:
Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.
With over 6 years of experience in tech publishing, Mani has edited and published more than 75 books covering a wide range of data science topics. Known for his strong attention to detail and technical knowledge, Mani specializes in creating clear, concise, and easy-to-understand content tailored for developers.
Write a C++ programme and initialize a 2d array of size [4][4] and display it. please solve it!!!
- unzillah
I did not understand the concept properly plz do say in simple way to understand for the students
- Reya
write c++ program that will ask the user to enter the array size, desired elements and output the total sum of elements stored in array ANYONE CAN ANSWER THIS PLEASE, asap. THANKYOU IN ADVANCE
- TAKOOOOHAKI
Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.
Full documentation for every DigitalOcean product.
The Wave has everything you need to know about building a business, from raising funding to marketing your product.
Stay up to date by signing up for DigitalOcean’s Infrastructure as a Newsletter.
New accounts only. By submitting your email you agree to our Privacy Policy
Scale up as you grow — whether you're running one virtual machine or ten thousand.
Sign up and get $200 in credit for your first 60 days with DigitalOcean.*
*This promotional offer applies to new accounts only.