【问题标题】:How do I initialize with a 2 dimensional initializer_list?如何使用 2 维 initializer_list 进行初始化?
【发布时间】:2018-06-22 21:45:32
【问题描述】:

我知道,向量类是通过以下方式初始化的:

Vector::Vector(initializer_list<double> lst)
    :size{static_cast<int>(lst.size())},elem{new double[static_cast<int>(lst.size())]}
    {
        copy(lst.begin(),lst.end(),elem);
    }

这是我的矩阵类:

class Matrix{
private:
    int row;
    int col;
    double elem**
public:
    //Default Constructor:
    Matrix(int row,int col);
    //Initialized list constructor:
    Matrix(initializer_list<initializer_list<double>> lst);

我想,我应该在初始化列表中使用初始化 lis 来创建初始化矩阵。从语法的角度来看,我该怎么做?

【问题讨论】:

  • 如果矩阵不是矩形,我的编译时功夫不足以提供编译器错误。
  • 默认构造函数不应该没有参数吗?
  • @user4581301 你不必:如果你初始化一个二维数组,编译器也不会抱怨:int mat[3][3] = { {1,2,3}, {9}, {6,7} };。在这里找到最大的行来确定列就足够了:-)
  • @Christophe 诅咒!你说的对!我生命中的一个小时没有浪费;我现在对constexprstatic_assert 的了解比我今天早上起床时对initializer_list 的了解要多得多。
  • @atru 这取决于矩阵是否可调整大小。当然,没有默认构造函数会有一些限制(例如,你不能构造一个 n 矩阵的向量)。

标签: c++ matrix initialization initializer-list


【解决方案1】:

这与您用于Vector 的原理相同,但通过列表进行迭代:

Matrix(initializer_list<initializer_list<double>> lst) : 
                                   row{lst.size()}, 
                                   col{0}   // not sure if all cols are same size
{
    for (auto &x: lst)     // iterate through outer list to find largest inner list
        if (x.size()>col)
            col = x.size();
    cout<<row<<"x"<<col<<endl;   // educational purpose only -> remove
    elem=new double*[row];       
    auto it=lst.begin();         // iterate through outer list 
    for (int i=0; i<row; i++, it++) {
        elem[i]=new double[col];    
        std::copy(it->begin(),it->end(),elem[i]); // copy current inner list
    }
}

有了这个,你可以处理一个像这样的二维列表:

Matrix m{ {1,2,3},{4,5,6},{7,8,9}}; 

Online demo

重要提示: 手动管理内存总是很痛苦且容易出错。使用std::vector 而不是指向动态分配的数组的指针会更容易。对于矩阵,您可以在向量向量或带有一些公式的扁平向量之间进行选择,以查找给定行和列的元素。

【讨论】:

  • 谢谢!是的,我感受到了这种痛苦(使用指针),但我这样做是为了更好地了解它们是如何工作的。
  • 只是一个小问题:你能解释一下 std::copy(it->begin(),it->end(),elem[i]);为什么这里的意思是我们复制了内部列表,而不是外部列表?因为它意味着 lst.begin().begin() ?
  • @Rob_Fir 是的:'it' 是遍历外部列表项的迭代器。当取消引用 'it' (例如 *it 或 it->)时,您可以处理迭代器指向的项目,这里是内部列表之一。由于这个元素本身就是一个列表(内部列表),您可以使用它的成员来获取自身的迭代器。所以 it->begin() 是内部列表之一的开始。
【解决方案2】:

我推荐使用std::array:

#include <array>

template<int ROWS, int COLUMS>
using Matrix = std::array<std::array<double, COLUMS>, ROWS>;

Matrix<3,3> m{ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0 };

std::vector:

#include <vector>

using Matrix = std::vector<std::vector<double>>;

Matrix m{ {1.0, 2.0, 3.0}, {4.0, 5.0, 6.0}, {7.0, 8.0, 9.0} };

或者从std::vector派生的class Matrix

#include <vector>

class Matrix
    : public std::vector<std::vector<double>>
{
public:
    Matrix( std::vector<std::vector<double>> && m )
        : std::vector<std::vector<double>>( m )
    {}
};

Matrix m( { {1.0, 2.0, 3.0}, {4.0, 5.0, 6.0}, {7.0, 8.0, 9.0} } );

【讨论】:

    猜你喜欢
    • 2019-04-16
    • 2011-07-29
    • 1970-01-01
    • 2016-12-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-02
    • 2017-11-16
    相关资源
    最近更新 更多