0

I have created a data structure that contains a multidimensional array member. The dimensions of this array are ultimately supplied by user input and are known at the construction of the struct, but not before. I have provided a minimal working example that hopefully demonstrates the problem:

struct MyStruct{
    int rows;
    int cols;
    float data[][];

    MyStruct(int m, int n) : rows(m), cols(n){
        data[m][n];
    }
};

In VSC I get a parsing error on float data[][]; that reads: 'an array may not have elements of this type'

So, is there a way to initialize the dimensions of a multi-dimensional array at the time of construction? Or do I need to create a new struct/class to hold the data?

  • If you need runtime defined sizes, you have to write your own (using one dimensional `std::vector`) or use ready solution like [boost::multi_array](https://www.boost.org/doc/libs/1_69_0/libs/multi_array/doc/user.html#sec_example) – Marek R Feb 08 '21 at 18:00
  • Objects in C++ have a fixed size. An object is allocated before it is constructed, so you cannot decide during construction how much space should have been allocated. That's putting the cart before the horse. – Drew Dormann Feb 08 '21 at 18:02
  • That said, if your question is "How do I create two dimensional storage, size known at runtime?" There are very many solutions. Some involving arrays. – Drew Dormann Feb 08 '21 at 18:04
  • [Here is a really simple `vector`-based solution](https://stackoverflow.com/a/2076668/4581301) – user4581301 Feb 08 '21 at 18:06

2 Answers2

3

How to declare a multidimensional array member in a C++ class or struct?

Like this:

struct MyStruct{
    float data[42][123];
};

The dimensions of this array are ultimately supplied by user input

This is not possible if the array is a member variable. The size of an array variable must be a compile time constant in C++. Furthermore, the size of an array element type must be known, so even dynamic arrays can only have constant size inner dimensions.

Or do I need to create a new struct/class to hold the data?

Firstly, you must create the array dynamically. Simplest solution is to use std::vector.

Secondly, you should use a flat single dimensional vector, where the rows are stored one after the other. Another, simpler alternative is a vector of vectors, but that is often inefficient unless you need specific operations such as reordering rows which are particularly fast in that case.

eerorika
  • 232,697
  • 12
  • 197
  • 326
  • Thank you for the explanation. I have a custom struct to store the data as a 1D array that will work. This saves me from proceeding down the wrong path in the future. – StillUsesFORTRAN Feb 08 '21 at 18:06
0

You should never use C-style arrays in C++. There is never a need for that.

And your question cries for a std::vector.

You could write

#include <vector>

struct MyStruct {
    std::vector<std::vector<float>> data{};
    MyStruct(size_t m, size_t n) {
        data.resize(m);
        for (auto& v : data) v.resize(n);
    }
};

int main() {
    MyStruct ms(5,8);
    return 0;
}

Since the vector can grow dynamically during runtime, there is no need to do all this resizing action during construction. Not necessary.

And also, rows and cols is not necessary. The vector knows its size.

So, best, if you would consider the std::vector as the solution.

A M
  • 14,694
  • 5
  • 19
  • 44
  • 2
    I've heard perspectives like this quite often on stackoverflow, though I'm not entirely convinced yet. Because the array will never change size/shape once declared (and will be used in frequently in large mathematical operations) it seems pointless to incur the (small) performance penalty of ```std::vector```. Is there anything wrong with this? – StillUsesFORTRAN Feb 08 '21 at 18:27
  • @DanielFust Practical and ideological often bump heads. My rule of thumb is stick to ideological until you really, really need that last few percent you can't get from the ideologically correct approach or their is no sound ideological approach. Don't force your code to follow a guideline if the guideline doesn't lend itself well to the intent. – user4581301 Feb 08 '21 at 19:19
  • If the size is fixed, the use a ````std::array````. If speed matters, use a ````std::valarray````, if it should only contain unique values, then use a ````std::unordered_set````, a ````std::set```` for sorted values. And so on and so on. Use, what is approriate, but not a C-Array in C++. But in the end. It is a free world and everybody can do what he wants in his private life . . . – A M Feb 08 '21 at 20:30