【问题标题】:How to initialize a 2D C-style array from a nested std::initializer_list?如何从嵌套的 std::initializer_list 初始化 2D C 样式数组?
【发布时间】:2020-01-19 18:49:06
【问题描述】:

我正在创建一个 Matrix<type, width, height> 类,我希望能够使用 initializer_list 对其进行初始化,例如:

Matrix<int, 2, 2> mat = Matrix<int, 2, 2>{ {1,2},{3,4} };

矩阵是使用T[height][width] 2D 数组实现的。

为此,我尝试制作一个构造函数,例如:

Matrix(std::initializer_list< std::initializer_list<T>> input);

但是,我不知道如何从列表中填充数组。我试过了

  • 使用memcpy(损坏的内存),

  • std::copy(似乎无法从 std::initializer_list),

  • 以及使用了赋值运算符()构造函数调用 (但是 2D 数组是不可赋值的并且 () 构造函数调用不能 编译)。

有没有其他方法,最好尽可能安全?

【问题讨论】:

  • 提示:range-for 是你的朋友。
  • 由于 initializer_list 是由底层数组实现的(根据cppreference),我想您可以从指向begin() 返回的第一个元素的指针(每个行元素的 begin() ; 外部列表仅包含代理初始化器列表)。这完全是反范式的,但到底是什么。

标签: c++ c++11 templates multidimensional-array stdinitializerlist


【解决方案1】:

您应该为Matrix(std::initializer_list&lt;/* here */&gt; list); 提供确切的类型。 然后要填充数组,您需要遍历传递的列表并填充数组。 (See live online)

#include <initializer_list> // std::initializer_list

template<typename T, std::size_t R, std::size_t C>
class Matrix
{
    T mArray2D[R][C]{};

public:
    Matrix(const std::initializer_list<T[C]> list)
    //                                 ^^^^^ --> type of the row
    {
        auto iter{ list.begin() }; // returns pointer to T[C]
        for (std::size_t row{}; row < R; ++row)
        {
            const auto& rowElements{ *iter };
            for (std::size_t col{}; col < C; ++col)
            {
                mArray2D[row][col] = rowElements[col];
            }
            ++iter;
        }
    }
};

现在在main() 中,您可以使用如下初始化列表初始化Matrix

Matrix<int, 2, 2> mat{ {1,2}, {3,4} };
// or
// Matrix<int, 2, 2> mat = { {1,2}, {3,4} };

如果您可以使用std::array,您可以执行以下操作。 (See live online)

#include <iostream>
#include <array>            // std::array
#include <initializer_list> // std::initializer_list

template<typename T, std::size_t R, std::size_t C>
class Matrix
{
    using RowType = std::array<T, C>;
    T mArray2D[R][C]{};

public:
    Matrix(const std::initializer_list<RowType> list)
    {
        auto iter{ list.begin() };
        for (std::size_t row{}; row < R; ++row)
        {
            const RowType& rowElements{ *iter };
            for (std::size_t col{}; col < C; ++col)
            {
                mArray2D[row][col] = rowElements[col];
            }
            ++iter;
        }
    }
};

如果类中的多维数组可以是std::array 类型为Tstd::array,您也可以使用std::copy(See live online)

#include <iostream>
#include <array>            // std::array
#include <initializer_list> // std::initializer_list
#include <algorithm>        // std::copy

template<typename T, std::size_t R, std::size_t C>
class Matrix
{
    using RowType = std::array<T, C>;
    using Array2D = std::array<RowType, R>;
    Array2D mArray{ RowType{} }; // initialize the matrix

public:
    Matrix(const std::initializer_list<RowType> list)
    {
       std::copy(list.begin(), list.end(), mArray.begin());
    }
};

【讨论】:

  • 谢谢,将底层数组更改为 std::array 并使用您的建议,效果很好!
  • @kubci98 之前的解决方案有一个错字,现在我添加了纯 c 样式数组的解决方案。查看更新。
猜你喜欢
  • 2011-01-26
  • 2016-12-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-04-16
  • 2010-09-18
  • 2011-07-29
  • 2015-04-16
相关资源
最近更新 更多