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.
#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::vector
s instead of built-in arrays would simplify things a lot.
#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