Referring to an entire row of arrays in a 2D array

Learn referring to an entire row of arrays in a 2d array with practical examples, diagrams, and best practices. Covers c++, arrays, 2d development techniques with visual explanations.

Referring to an Entire Row of Arrays in a 2D Array in C++

Hero image for Referring to an entire row of arrays in a 2D array

Learn various techniques to effectively refer to and manipulate entire rows within a 2D array in C++, covering raw arrays, std::vector<std::vector<T>>, and std::array<std::array<T, N>, M>.

In C++, working with 2D arrays often involves accessing individual elements. However, there are scenarios where you need to treat an entire row as a single unit, perhaps to pass it to a function, copy it, or perform row-specific operations. This article explores different methods for referring to an entire row in various C++ 2D array implementations, including C-style arrays, std::vector<std::vector<T>>, and std::array<std::array<T, N>, M>.

Understanding 2D Arrays in C++

Before diving into row-referencing, it's crucial to understand how 2D arrays are structured in C++. They are essentially arrays of arrays. For a C-style int arr[3][4], it's an array of 3 elements, where each element is an array of 4 integers. This fundamental concept dictates how we can access and refer to rows.

graph TD
    A[2D Array] --> B["Array of Rows (e.g., `int arr[3][4]`)"]
    B --> C1["Row 0 (e.g., `arr[0]`)"]
    B --> C2["Row 1 (e.g., `arr[1]`)"]
    B --> C3["Row 2 (e.g., `arr[2]`)"]
    C1 --> D1["Element (e.g., `arr[0][0]`)"]
    C1 --> D2["Element (e.g., `arr[0][1]`)"]
    C2 --> D3["Element (e.g., `arr[1][0]`)"]
    style A fill:#f9f,stroke:#333,stroke-width:2px
    style B fill:#bbf,stroke:#333,stroke-width:2px
    style C1 fill:#ccf,stroke:#333,stroke-width:1px
    style C2 fill:#ccf,stroke:#333,stroke-width:1px
    style C3 fill:#ccf,stroke:#333,stroke-width:1px
    style D1 fill:#eee,stroke:#333,stroke-width:0.5px
    style D2 fill:#eee,stroke:#333,stroke-width:0.5px
    style D3 fill:#eee,stroke:#333,stroke-width:0.5px

Conceptual structure of a 2D array as an array of rows.

Referring to Rows in C-Style 2D Arrays

For a traditional C-style 2D array like int arr[ROWS][COLS], accessing arr[i] gives you a pointer to the i-th row. Specifically, it decays to a pointer to the first element of that row, which is of type int* (or T* for a generic type T). However, when passing it to a function, you often need to specify the size of the inner array.

#include <iostream>

const int COLS = 4;

// Function to print a row
void printRow(int* rowPtr, int numCols) {
    for (int i = 0; i < numCols; ++i) {
        std::cout << rowPtr[i] << " ";
    }
    std::cout << std::endl;
}

// Function to modify a row (using a pointer to an array)
void modifyRow(int (*row)[COLS]) {
    for (int i = 0; i < COLS; ++i) {
        (*row)[i] *= 2;
    }
}

int main() {
    int arr[3][COLS] = {
        {1, 2, 3, 4},
        {5, 6, 7, 8},
        {9, 10, 11, 12}
    };

    std::cout << "Original array:\n";
    for (int i = 0; i < 3; ++i) {
        printRow(arr[i], COLS); // arr[i] decays to int*
    }

    std::cout << "\nModifying row 1:\n";
    modifyRow(&arr[1]); // Pass address of the row

    std::cout << "Array after modification:\n";
    for (int i = 0; i < 3; ++i) {
        printRow(arr[i], COLS);
    }

    return 0;
}

Demonstrates passing C-style array rows using pointers.

Referring to Rows in std::vector<std::vector<T>>

The std::vector<std::vector<T>> is a more flexible and modern way to represent 2D arrays in C++. Each inner std::vector<T> represents a row. This makes referring to an entire row straightforward, as you can directly access the inner vector.

#include <iostream>
#include <vector>
#include <numeric> // For std::iota

// Function to print a row (takes a const reference to a vector)
void printVectorRow(const std::vector<int>& row) {
    for (int val : row) {
        std::cout << val << " ";
    }
    std::cout << std::endl;
}

// Function to modify a row (takes a non-const reference to a vector)
void modifyVectorRow(std::vector<int>& row) {
    for (int& val : row) {
        val += 10;
    }
}

int main() {
    std::vector<std::vector<int>> matrix = {
        {1, 2, 3},
        {4, 5, 6},
        {7, 8, 9}
    };

    std::cout << "Original matrix:\n";
    for (const auto& row : matrix) {
        printVectorRow(row);
    }

    std::cout << "\nModifying row 1:\n";
    modifyVectorRow(matrix[1]); // Pass the std::vector<int> by reference

    std::cout << "Matrix after modification:\n";
    for (const auto& row : matrix) {
        printVectorRow(row);
    }

    // Example of adding a new row
    std::vector<int> newRow(3);
    std::iota(newRow.begin(), newRow.end(), 100); // Fills with 100, 101, 102
    matrix.push_back(newRow);

    std::cout << "\nMatrix after adding a new row:\n";
    for (const auto& row : matrix) {
        printVectorRow(row);
    }

    return 0;
}

Demonstrates referring to and manipulating rows in std::vector<std::vector<T>>.

Referring to Rows in std::array<std::array<T, N>, M>

For fixed-size 2D arrays where dimensions are known at compile time, std::array<std::array<T, N>, M> offers type safety and performance benefits similar to C-style arrays, but with an STL-like interface. Each inner std::array<T, N> represents a row.

#include <iostream>
#include <array>
#include <numeric>

const int COLS_STD_ARRAY = 4;
const int ROWS_STD_ARRAY = 3;

// Function to print a row (takes a const reference to std::array)
void printStdArrayRow(const std::array<int, COLS_STD_ARRAY>& row) {
    for (int val : row) {
        std::cout << val << " ";
    }
    std::cout << std::endl;
}

// Function to modify a row (takes a non-const reference to std::array)
void modifyStdArrayRow(std::array<int, COLS_STD_ARRAY>& row) {
    for (int& val : row) {
        val *= 3;
    }
}

int main() {
    std::array<std::array<int, COLS_STD_ARRAY>, ROWS_STD_ARRAY> grid = {
        std::array<int, COLS_STD_ARRAY>{1, 2, 3, 4},
        std::array<int, COLS_STD_ARRAY>{5, 6, 7, 8},
        std::array<int, COLS_STD_ARRAY>{9, 10, 11, 12}
    };

    std::cout << "Original grid:\n";
    for (const auto& row : grid) {
        printStdArrayRow(row);
    }

    std::cout << "\nModifying row 0:\n";
    modifyStdArrayRow(grid[0]); // Pass the std::array<int, COLS_STD_ARRAY> by reference

    std::cout << "Grid after modification:\n";
    for (const auto& row : grid) {
        printStdArrayRow(row);
    }

    return 0;
}

Demonstrates referring to and manipulating rows in std::array<std::array<T, N>, M>.