如何用initializer_lists初始化一个二维数组?

How to initialize a two dimensional array using initializer_lists?

我编写了此构造函数以使用 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]{};
    }
};

但是,这段代码显示了这个错误:

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();

是的,我知道每列的长度可能不同,但为了简单起见,我删除了一些代码。实际上,我正在为 C++ 编写数学矩阵数据结构。而且我也知道二维数组可以当成一维的,可以很方便的用一维初始化initializer_list.

如何绕过这个错误?为什么这里会出现此错误?

你需要先创建一个指针数组,然后用int数组初始化它们。请注意,如果任何分配引发异常,这可能会泄漏。

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

然后类似地delete每个子数组。

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

尽管如此,除非您受益于直接拥有内存,否则请考虑使用 std::vector<std::vector<int>>(或 std::unique_ptr<std::unique_ptr<int[]>[]>)。

如果你的行长度是一个编译时常量,C++11 允许

auto array = new int [row_size][CONSTANT];

否则,您可以使用指向数组的指针数组来允许像连续二维数组这样的二维语法,即使它不是一个有效的单一大型分配。您可以使用循环对其进行初始化,如下所示:

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];
        for(int i = 0; i < row_size; ++i)
            array[i] = new int[column_size];
    }

我做了这个例子,所以你可以输入:

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

尚未经过全面测试,但可以帮助您入门。 它还展示了如何在不需要“新建”或“删除”的情况下实现它。

#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);
}