c++arrayspointersmultidimensional-arrayconst-pointer

How to initialize int *const *const?


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?


Solution

  • 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";
    }