0

I've coded this constructor to initialize my two-dimensional array using initializer_lists.

using namespace std;

class TwoArray{
    int** array;

public:
    TwoArray(initializer_list<initializer_list<int>> list_){
        const size_t row_size = list_.size();
        const size_t column_size = list_.begin()->size();
        
        array = new int[row_size][column_size]{};
    }
};

But, this code shows this error:

main.cpp: In constructor ‘TwoArray::TwoArray(std::initializer_list<std::initializer_list<int> >)’:
main.cpp:19:48: error: array size in new-expression must be constant
         array = new int[row_size][column_size]{};
                                                ^
main.cpp:19:48: error: the value of ‘column_size’ is not usable in a constant expression
main.cpp:13:22: note: ‘column_size’ was not initialized with a constant expression
         const size_t column_size = list_.begin()->size();

And yes, I know that the length of each column may be different, but I've stripped out some code for simplicity. Actually, I am coding a mathematical matrix data structure for C++. And I also know that the two-dimensional array can be treated as one-dimensional and can be initialized easily using one-dimensional initializer_list.

How do I bypass this error? And why is this error present here?

4
  • What do you think new T[n][m] is doing? Commented Sep 4, 2021 at 10:11
  • Evg , I think that new T[n][m] is allocating a new two-dimensional array of order n*m Commented Sep 4, 2021 at 10:13
  • 1
    Take a look: en.cppreference.com/w/cpp/language/new#Explanation Commented Sep 4, 2021 at 10:17
  • Constructor TwoArray(initializer_list<initializer_list<int>> list_) is private. Commented Sep 4, 2021 at 14:34

2 Answers 2

1

You need to create one array of pointers first, then initialize them with arrays of int. Note that this may leak if any allocation throws an exception.

array = new int*[row_size];
for(std::size_t i = 0; i < row_size; ++i)
    array[i] = new int[column_size]{};

And then analogously delete each sub-array.

for(std::size_t i = 0; i < row_size; ++i)
    delete[] array[i];
delete[] array;

Although, unless you benefit from owning the memory directly, consider using std::vector<std::vector<int>> (or std::unique_ptr<std::unique_ptr<int[]>[]>) instead.

Sign up to request clarification or add additional context in comments.

1 Comment

Or even better, linear std::vector<int> with some index arithmetic.
1

I made this example so you can type:

array<int, 2, 3> my_array{ {{0,1}, {2,3}, {4,5}} };

Not fully tested yet but it will get you started. It also shows how you can achieve it without needing "new" or "delete".

#include <cassert>
#include <array>

template<typename type_t, size_t COLS, size_t ROWS>
struct array
{
    array(const type_t(&values)[ROWS][COLS])
    {
        for (auto c = 0; c < COLS; ++c)
        {
            for (auto r = 0; r < ROWS; ++r)
            {
                at(c, r) = values[r][c];
            }
        }
    }

    type_t& at(const std::size_t column, const std::size_t row)
    {
        assert(row < m_rows);           // row out of range
        assert(column < m_columns);     // column out of range

        auto index = (row * COLS) + column;
        return m_data[index];
    }

    type_t& operator()(const std::size_t column, const std::size_t row)
    {
        return at(column, row);
    }

private:
    const type_t m_rows{ ROWS };
    const type_t m_columns{ COLS };
    std::array<type_t, ROWS* COLS> m_data{};
};

int main()
{
    array<int, 2, 3> arr{ {{0,1}, {2,3}, {4,5}} };

    assert(arr(1, 1) == 3);
    assert(arr(1, 2) == 5);
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.