Home > Blockchain >  pointer to pointer of vector yields 3D vector?
pointer to pointer of vector yields 3D vector?

Time:11-12

I have been looking through some legacy code and found this little snippet:

std::vector<int>** grid = new std::vector<int>*[10];
for (int k = 0; k < 10; k  ) 
    grid[k] = new std::vector<int>[10];

And then later on, the original developer is calling this command here:

grid [i][j].push_back(temp);

I was under the impression that the [i][j] would return the value in the nested vector, but by using push_back implies that there is a pointer to a vector at that location? I'm confused where this third vector arises from.

Also, is there a better approach? would a triple nested vector also achieve the same results as the above code?

Thanks in advance!

CodePudding user response:

grid[i][j] is a reference to a std::vector<int>.

Rewriting things may clarify what you have.

[Demo]

#include <fmt/ranges.h>
#include <vector>

int main() {
    using line_t = std::vector<int>;  // line is a vector of ints
    using matrix_t = line_t*;  // matrix is an array of lines
    using grid_t = matrix_t*;  // grid is an array of matrices

    // Same as: grid_t grid{ new std::vector<int>*[3] };
    grid_t grid{ new matrix_t[3] };
    int v{};
    for (int k = 0; k < 3; k  ) {  // we walk each matrix
        auto& matrix{ grid[k] };
        matrix = new line_t[3];
        for (int l = 0; l < 3; l  , v  ) {  // we walk each line
            // Same as: auto& line{ grid[k][l] };
            auto& line{ matrix[l] };
            line = std::vector<int>(3, v);
        }
    }

    fmt::print("Grid\n\n");
    for (int k{0}; k < 3; k  ) {
        fmt::print("Matrix {}\n", k);
        auto& matrix{ grid[k] };
        for (int l{0}; l < 3; l  ) {
            auto& line{ matrix[l] };
            fmt::print("{}\n", line);
        }
        fmt::print("\n");
    }
}


// Outputs:
//
//   Grid
//
//   Matrix 0
//   [0, 0, 0]
//   [1, 1, 1]
//   [2, 2, 2]
//
//   Matrix 1
//   [3, 3, 3]
//   [4, 4, 4]
//   [5, 5, 5]
//
//   Matrix 2
//   [6, 6, 6]
//   [7, 7, 7]
//   [8, 8, 8]

Using std::vectors instead of built-in arrays would simplify things a lot.

[Demo]

#include <algorithm>  // fill
#include <fmt/ranges.h>
#include <vector>

int main() {
    using line_t = std::vector<int>;  // line is a vector of ints
    using matrix_t = std::vector<line_t>;  // matrix is a vector of lines
    using grid_t = std::vector<matrix_t>;  // grid is a vector of matrices

    grid_t grid(3, matrix_t(3, line_t(3)));
    int v{};
    for (auto& matrix : grid) {
        for (auto& line : matrix) {
            std::ranges::fill(line, v  );
        }
    }

    fmt::print("Grid\n\n");
    for (int k{0}; k < 3; k  ) {
        fmt::print("Matrix {}\n", k);
        fmt::print("{}\n\n", fmt::join(grid[k], "\n"));
    }
}

CodePudding user response:

What you have is a mess written by someone who doesn't understand C .

grid[i][j] is a reference (not a pointer) to a std::vector<int>.

Also, is there a better approach? would a triple nested vector also achieve the same results as the above code?

Yes std::vector<std::vector<std::vector<int>>> grid { 10, { 10, {} } }; would be that.

However, if you want to ensure that there are equal number of elements in each, you should use a matrix class.

somelib::matrix<std::vector<int>> grid(10, 10); // probably only does one allocation of 100 vectors

CodePudding user response:

I think your confusion is that there are two dimensions made up of pointers and one dimension made up of a vector.

In total, there are 100 vectors with integers.

grid[]    -> contains 10 pointers which each point to an array of vector pointers
grid[][]  -> contains 10 pointers to vectors
*grid[][] -> a vector of integers
  • Related