C++11 dynamic multidimensional array of any type using vector/initilizer list

Viewed 2271

How do you create a multidimensional array (matrix) whose dimensions are determined at runtime.

The best way seems to be to take a vector of dimensions for construction and also a vector of offsets to access individual elements

This will also allow using initializer lists:

This should take a matrix of types determined at compile time, so templates make sense

C++11 features should be used as appropriate, bonus points for lambdas

Example usage:

int main(int, char **)
{
        static const std::size_t d1{2};
        static const std::size_t d2{3};
        static const std::size_t d3{4};
        multi_vec<std::size_t> q({d1,d2,d3});

        for (std::size_t i1=0; i1 < d1; ++i1)
                for (std::size_t i2=0; i2 < d2; ++i2)
                        for (std::size_t i3=0; i3 < d3; ++i3)
                                q[{i1,i2,i3}]=foo(i1,i2,i3);

        for (std::size_t i1=0; i1 < d1; ++i1)
                for (std::size_t i2=0; i2 < d2; ++i2)
                        for (std::size_t i3=0; i3 < d3; ++i3)
                                std::cout << "{"
                                        << i1 << ","
                                        << i2 << ","
                                        << i3 << "}=> "
                                        << foo(i1,i2,i3) << "=="
                                        << q[{i1,i2,i3}]
                                        << ((foo(i1,i2,i3) == q[{i1,i2,i3}])
                                              ? " good" : " ERROR")
                                << std::endl;
};
3 Answers

You use C. Honestly, C's dynamic arrays are superior to anything C++ offers. Here is the code for a 3D array:

//Allocation, the type needs some effort to understand,
//but once you do understand it, this is easy:
int width = 7, height = 8, depth = 9;
int (*array)[height][width] = malloc(depth*sizeof(*array));

//Filling, completely natural...
for(int z = 0; z < depth; z++) {
    for(int y = 0; y < height; y++) {
        for(int x = 0; x < width; x++) {
            array[z][y][x] = 42;
        }
    }
}

//Deallocation, trivial...
free(array);

A 3D array is nothing more or less than a 1D array of 2D arrays (which are 1D arrays of 1D arrays in turn), so you declare a pointer *array to a 2D array of integers int (...)[heigh][width], and allocate space for depth such elements malloc(depth*sizeof(*array)). This is fully analogous to creating a 1D array with int *array = malloc(length*sizeof(*array));. The rest is array-pointer-decay magic.

This works is C, because C allows array types to contain dynamic sizes (since C99). It's like defining two constants with the declared sizes at the point of the declaration. C++, on the other hand, still insists on array sizes being compile-time constants, and thus fails to allow you multi-dimensional arrays of dynamic size.

Related