C ++矩阵类-建议

| 我正在尝试在C ++中构建模板化的Matrix类。以下是其实现。 到目前为止,我已经实现了两个运算符+,+ =只是为了对它的外观有所了解,我认为最好在继续进行之前先征求反馈。 整个实现是公共的,也没有显式的绑定/错误检查,这是因为它并不意味着要成为完整的矩阵库,因此可以避免不必要的代码。 如果有人可以对此发表评论并提出一些改进或建议,那将非常有帮助。 谢谢。
template<class T>
class Matrix
{
    public:
    int r,c;
    vector< vector< T > >mat;

    Matrix() {}

    // Constructor to set the size of the matrix
    Matrix(int _r,int _c)
    {
        r=_r;c=_c;
        mat.resize(r);
        for(int i=0;i<r;i++)
            mat[i].resize(c);
    }
    // Constructor to build a matrix from a C 2d array
    // Pointer to the first element is passed (&arr[0][0])
    Matrix(T *arr,int _r,int _c)
    {
        r=_r;c=_c;
        mat.resize(r);
        for(int i=0;i<r;i++)
            for(int j=0;j<c;j++)
                mat[i].push_back(arr[i*c+j]);
    }
    template<typename U>
    Matrix<T>& operator +=(const Matrix<U>&M)
    {
        for(int i=0;i<r;i++)
            for(int j=0;j<c;j++)
                mat[i][j]+=static_cast<T>(M.mat[i][j]);
        return *this;
    }
    template<typename U>
    Matrix<T> operator +(const Matrix<U>&M)
    {
        Matrix<T>tmp=*this;
        return tmp+=M;
    }
};

template<typename T>
istream& operator >>(istream &in,Matrix<T>&M)
{
    in>>M.r>>M.c;
    Matrix<T>tmp(M.r,M.c);
    for(int i=0;i<M.r;i++)
        for(int j=0;j<M.c;j++)
            in>>tmp.mat[i][j];
    M=tmp;
    return in;
}
template<typename T>
ostream& operator <<(ostream &out,Matrix<T>M)
{
    for(int i=0;i<M.r;i++)
    {
        for(int j=0;j<M.c;j++)
            cout<<M.mat[i][j]<<\" \";
        cout<<endl;
    }
    return out;
}
编辑: 谢谢大家的建议。 我只有一个小问题,说我确实要执行错误检查(例如:检查范围,有效参数等。)但是我确实希望为用户提供一个选项来完全禁用错误检查,请问有什么好的方法实施这个? 我需要的是例如示例:`ios_base :: sync_with_stdio(0);。 再次感谢。     
已邀请:
要点: 使用单个ѭ1而不是
std::vector<std::vector<T>>
。用y * r + x对其建立索引-使用和运算符重载使其更容易(请参阅下一点)。这样会提高内存使用效率,并稍微加快速度(并且初始化会容易得多::3ѭ)。 将您的数据成员设为私有,以保护矩阵免受意外大小更改。例如,用户代码当前可以调整向量的大小,但保留旧的
r
c
。 重载
operator()
以访问矩阵(const和non-const)。如果确实必须使用
matrix[r][c]
语法而不是
matrix(r,c)
,请考虑重载
operator[]
并将迭代器返回到正确的行(向量迭代器是随机访问的,因此它们将提供
operator[]
)。 而是将
operator+
实现为非朋友非成员函数-改进封装! 按照其他建议使用初始化列表。 让当前采用
T*
的构造函数采用迭代器代替。这样,您就可以自动获得指针支持以及许多其他很棒的功能,例如调试迭代器的范围检查,兼容值类型的自动类型转换以及对所有其他随机访问迭代器的支持。还可以考虑按行填充矩阵,因此也可以使用正向迭代器。     
如果您想知道它是如何正确完成的,请参阅Eigen项目的实现: https://bitbucket.org/eigen/eigen/src/49e00a2e570c/Eigen/src/Core/Matrix.h https://bitbucket.org/eigen/eigen/src/49e00a2e570c/Eigen/src/Core/MatrixBase.h Eigen是用于C ++的大量模板快速矩阵库。我敢肯定那里有很多用处。     
1。为构造函数使用初始化列表,如
Matrix (...) : r(_r), c(_c)
2.
operator +
可以简单地是
{ return this->Add(M) }
(假设类型名
T
U
兼容,并且您已经实现了一些Add()方法)。 3.如果要从2D数组构造某些东西,请使用以下技术:
template<typename T>
class Matrix {
public: // ...
  void Construct (T *arr)
  {
    mat.resize(r);
    for(int i=0;i<r;i++)
      for(int j=0;j<c;j++)
        mat[i].push_back(arr[i*c+j]);
  }
  template<size_t ROW, size_t COL>
  Matrix(T (&arr)[ROW][COL]) : r(ROW), c(COL)
  {
    Construct(arr);
  }
//...
};
因此,您在调用时不必传递2D数组的大小,这样可以减少出错的可能性。 为了提高可读性,可以为类成员使用更好的名称::19ѭ或
t_r
。     
在初始化构造函数参数时使用初始化列表:
 Matrix(int _r,int _c)
    {
        r=_r;c=_c;
.. 应该:
 Matrix(int _r,int _c) : r(_r), c(_c)
    {
        ....
    
您可能想将
r
c
mat
成员设为私人。 您的流运算符不是对称的(
operator<<
不会写出
r
c
)。     
我不会使用向量载体来实现这一目标。这样,您将为所有查找添加相当多的开销,而无需任何实际需要。只需分配一个ѭ16的一维或二维数组,然后在您的类中使用该数组即可。这也将允许快速复制到其他对象实例,而不必遍历所有字段以及重置整个矩阵。 另外,当以后不应该更改成员时,您应该使它们成为const(在您的示例中为
r
c
)。要初始化它们,只需使用Tony \帖子中的构造函数列表。     
您在浪费keeping32ѭ和
_c
的时间,因为向量保持自己的大小。     
我想知道为什么在此类初始化中使用了非常昂贵的push_back函数:
// Pointer to the first element is passed (&arr[0][0])
Matrix(T *arr,int _r,int _c)
{
    r=_r;c=_c;
    mat.resize(r);
    for(int i=0;i<r;i++)
        for(int j=0;j<c;j++)
            mat[i].push_back(arr[i*c+j]);
}
由于您已经具有行数和列数,因此请考虑以下事项:
// Pointer to the first element is passed (&arr[0][0])
Matrix(T *arr,int _r,int _c)
{
    r=_r;c=_c;
    mat.resize(r);
    for(int i=0;i<r;i++)
        mat[i].resize(c);
        for(int j=0;j<c;j++)
            mat[i][j]= arr[i*c+j];
}
    
如果要考虑速度,请不要自己实现矩阵库,而要使用Boost库,我已经在某些项目中使用了它们,并且在32位和64位架构上都表现出色     

要回复问题请先登录注册