2

我知道我可以通过使用数组来存储 Matrix 的数据来做到这一点。

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

但是我想这样做并改用向量,因为当矩阵变大并且堆栈空间用完时,使用数组非常糟糕

Matrix m(2, 2) = { 1, 2
                   3, 4 };

可以这样做(或类似的事情)吗?

4

1 回答 1

3

如果您在编译时有固定大小,但想使用动态分配,您可以单独选择每个对象的分配类型(“堆栈”/“堆”)或将动态分配构建到Matrix类中。

类外动态分配的一个例子Matrix。请注意,使用初始化列表可以防止在编译时检查传递给 ctor at 的元素数量(而不是通过声明contexpr的实例Matrix)。因此,我引入了一个相当愚蠢的补充来演示编译时大小检查。

#include <memory>
#include <iostream>
#include <array>

template < typename T, std::size_t rows, std::size_t columns >
struct Matrix
{
public:
    Matrix(std::initializer_list<T> p)
    {
       if(p.size() != rows*columns) { /* throw */ }

       std::copy( p.begin(), p.end(), storage_member.begin() );
    }
    Matrix(std::array<T, columns*rows> const& p)
    {
       std::copy( p.begin(), p.end(), storage_member.begin() );
    }

    Matrix(std::initializer_list< std::initializer_list<T> > p)
    {
       if(p.size() != rows) { /* throw */ }

       auto itRow = p.begin();
       for(std::size_t row = 0; row < rows; ++row, ++itRow)
       {
          if(itRow->size() != columns) { /* throw */ }

          auto itCol = itRow->begin();
          for(std::size_t col = 0; col < columns; ++col, ++itCol)
          {
             storage_member[col+row*columns] = *itCol;
          }
       }
    }
    Matrix(std::array<std::array<T, columns>, rows> const& p)
    {
       for(std::size_t row = 0; row < rows; ++row)
       {
          for(std::size_t col = 0; col < columns; ++col)
          {
             storage_member[col+row*columns] = p[row][col];
          }
       }
    }

    // getters, setters
    T& operator() (std::size_t row, std::size_t col)
    {
        return storage_member[col+row*columns];
    }
private:
    // storage, e.g.
    std::array<T, columns*rows> storage_member;
};

template < typename T, typename... TP>
constexpr std::array<T,sizeof...(TP)+1> m(T&& p, TP... pp)
{
   return {{p, pp...}};
}

// usage:
int main()
{
   using My_Matrix_Type = Matrix < int, 2, 2 >;

   std::unique_ptr < My_Matrix_Type > pmyMatrix0{ new My_Matrix_Type( {1,2,3,4} ) };
   std::unique_ptr < My_Matrix_Type > pmyMatrix1{ new My_Matrix_Type( {{1,2},{3,4}} ) };

   // with compile-time size checks
   std::unique_ptr < My_Matrix_Type > pmyMatrix2{ new My_Matrix_Type( m(1,2,3,4) ) };
   std::unique_ptr < My_Matrix_Type > pmyMatrix3{ new My_Matrix_Type( m(m(1,2), m(3,4)) ) };
   // a more fancy but possible syntax, would require some additional effort:
   //std::unique_ptr < My_Matrix_Type > pmyMatrix4{ new My_Matrix_Type( b(1,2)(3,4) ) };


   std::cout << (*pmyMatrix0)(1,1) << std::endl;
   std::cout << (*pmyMatrix1)(1,1) << std::endl;
   std::cout << (*pmyMatrix2)(1,1) << std::endl;
   std::cout << (*pmyMatrix3)(1,1) << std::endl;
}

在上面的示例中,您可以立即用storage_member动态分配的数组替换以使动态分配内置。


如果您在编译时不知道大小,则必须将动态分配构建到Matrix类中(如上所述)。正如您可以推断出 2 级初始化器列表的大小(列、行),您只需删除采用固定大小数组的 ctor 并更改采用 1 级初始化器列表的 ctor,例如:

template < typename T > // no size parameters!
struct Matrix
{
    Matrix(std::size_t columns, std::size_t rows, std::initializer_list<T> p);
    Matrix(std::initializer_list< std::initializer_list<T> > p);
    // maybe an additional ctor for dynamically allocated arrays

    // getters, setters, data members
};

// usage:
Matrix myMatrix0( 2, 2, {1,2,3,4} );
Matrix myMatrix1( {{1,2},{3,4}} );
于 2013-04-14T13:16:49.347 回答