2

I need a 2d array with fixed width and height that can only change the individual values stored in it. It is declared in a header and later initialized in a source file.

What I found made me try the following snippets; unfortunately questions were about either 1d or non-const arrays and did not match my situation.

int *const *const a = new int[10][10];
int *const *const b = new int[10][10]();
int *const *const c = new int*[10];
for (int i = 0; i < 10; ++i) {
    c[i] = new int[10];
}

My hope was in the last example, but how can I use the "inner" arrays of c if they are not initialized and I am not able to initialize them since they are const?

Do I not need a different type for this array? I was thinking about int d[][] but it doesn't have constant width and height.
It seems to me like a paradox (if it exists in the c++ world), am I missing something?

Al.G.
  • 4,327
  • 6
  • 31
  • 56
  • 2
    A 2D array with fixed width and height would be `int a[10][10]`. You're creating arrays of pointers. – molbdnilo Feb 28 '16 at 19:37
  • This forces me know the size in the header, which I do not yet know. That's why I wanted int *const *const declaration. – Al.G. Feb 28 '16 at 19:42
  • Or is it a bad idea to have such arrays? I could remove it from the header and have a getter, but isn't this an overkill? Even this way, does it turn to be impossible to initialize such arrays? Then why would they exist? – Al.G. Feb 28 '16 at 19:46
  • 1
    You can initialize it as non const and then return a const copy of the pointer. Wrap the non const into the private section of a class, providing also the allocation/deallocation in the constructor/destructor. – DarioP Feb 28 '16 at 19:48
  • Are the dimensions known at compile time or only at runtime? – Christian Hackl Feb 28 '16 at 20:05
  • @DarioP thanks, this did the trick. Since I wanted `const` just because it is supposed to be constant, I think I can save such complexity and use a non-const array. – Al.G. Feb 28 '16 at 20:09
  • @ChristianHackl I have a separate config header with these values (#defined) and didn't want to include it in my class header file, but if I have to, I think I will. – Al.G. Feb 28 '16 at 20:09

2 Answers2

2

I was thinking about int d[][] but it doesn't have constant width and height.

int d[][] does not make sense (and will be rejected by the compiler). As far as multi-dimensional arrays are concerned, only the first dimension's size can be omitted to denote an incomplete type. The other dimensions' sizes are part of the type. You cannot omit them, much like you cannot omit the int.

In other words, if you have something like int d[5][10], then you can think of it as a one-dimensional array of element type int[10]. Generally, think of multi-dimensional arrays as a special case of one-dimensional arrays. It will make everything easier to understand.


The best solution to your problem in C++ is to create a class with private std::array<T, Width * Height> data; and int width member variables inside, and calculate the array offset from individual x and y arguments in a public member function, for example:

T& operator()(int x, int y)
{
    return data[y * width + x];
}

If the dimensions are only known at run-time, then the only thing you have to change is using std::vector instead of std::array. Storage will still be contiguous.

Here is a complete example:

#include <vector>
#include <iostream>

class Matrix
{
public:
    Matrix(int width, int height, int value) :
        width(width),
        data(width * height, value)
    {}

    int& operator()(int x, int y)
    {
        return data[y * width + x];
    }

private:
    int width;
    std::vector<int> data;
};

int main()
{
    Matrix m(5, 10, 123);
    std::cout << m(7, 8) << "\n";
    m(7, 8) = 124;
    std::cout << m(7, 8) << "\n";
}
Christian Hackl
  • 27,051
  • 3
  • 32
  • 62
1

My hope was in the last example, but how can I use the "inner" arrays of c if they are not initialized and I am not able to initialize them since they are const?

That's not really true at all:

int * const * const c = new int*[10]
{
    new int[10], new int[10], new int[10], new int[10], new int[10],
    new int[10], new int[10], new int[10], new int[10], new int[10]
};
Jts
  • 3,447
  • 1
  • 11
  • 14
  • Yeah, but OP added in comment - "This forces me know the size in the header, which I do not yet know. That's why I wanted int *const *const declaration." – zoska Feb 28 '16 at 20:14