运算符重载的矩阵乘法

Matrix Multiplication with operator overloading

本文关键字:重载 运算符      更新时间:2023-10-16

我正试图为我构建的矩阵类创建一个重载运算符。我的矩阵类将矩阵存储在一个动态分配的多维数组中。我只是想通过将两个完全相同的矩阵相乘来测试我的重载运算符,并显示输出。我得到了奇怪的结果,我相信这与我的for循环中的一个条件有关。然而,我已经浏览了所有的for循环,没有发现任何错误。我相乘得到的矩阵都是6x6。

我的操作员超载

template <typename T>
const matrix<T> matrix<T>::operator * (const matrix& right) const
{
    matrix<T> c = right;
    int sum_elems;
    for( int i = 0; i < this->rows - 1; ++i)
    {
        for(int j = 0; j < right.cols - 1; ++j)
        {
            sum_elems = 0;
            for( int k = 0; k < right.rows - 1; ++k)
            {
                sum_elems += this->the_matrix[i][k] * right.the_matrix[k][j];
            }
            c.the_matrix[i][j] = sum_elems;
        }
    }
    return c;
}                 

现在我在主功能中调用过载操作员:

std::cout << my_matrix;
matrix<int> copy_matrix;
copy_matrix = my_matrix * my_matrix; 
std::cout << copy_matrix;

我的输出:

  The Matrix:
 0  1  0  1  1  0
 1  0  1  0  1  1
 0  1  0  1  0  1
 1  0  1  0  1  0
 1  1  0  1  0  1
 0  1  1  0  1  0
   The Matrix:
 -1  33  139587680  18  38  75
 139587680  18  38  75  157  1
 139587712  38  1470  4365  10411  1
 139587744  75  4365  19058932  64514866  0
 139587776  157  10411  64514866  1136204102  1
 139596144  1  1  0  1  0

正如你所看到的,我似乎在我的一个数组上越界了。不过我似乎找不到哪里。我感谢你事先的帮助。

编辑:根据要求,我完全实现了矩阵类

矩阵定义:

template <typename T>
class matrix
{
    public:
        //Default Constructor
        matrix();
        //Overloaded Constructor
        matrix(std::ifstream&, const char*);
        //Copy Constructor
        matrix(const matrix&);
        //Destructor
        ~matrix();

        //overloaded operators
        T* operator [] (T);
        const matrix operator * (const matrix&) const;
        matrix& operator = (const matrix&);
        friend std::ostream& operator << <T> (std::ostream&, const matrix<T>&); 

    private:
        T** the_matrix;
        unsigned rows, cols;

矩阵实现:

/* Template version of matrix class */
/*---------------------------------------------------------------------------*/
// Default contructor
template <typename T>
matrix<T>::matrix() { }
// Overloaded contructor
template <typename T>
matrix<T>::matrix( std::ifstream& in, const char* file)
{
    // declare the variables to be used
    T vertices, edges, u, v;
    std::string line;
    // open file for reading
    in.open(file);
    // get number of vertices
    in >> vertices;

    // throw away second line   
    std::getline(in, line);
    std::getline(in, line);
    // get number of edges and dump them in two arrays
    in >> edges;
    T edge1 [edges];
    T edge2 [edges];
    int j = 0, k = 0;
    for(int a = 0; a < edges; ++a)
    {    
        in >> u >> v;
        edge1[j] = u;
        edge2[k] = v;
        ++j;
        ++k;
    }
    in.close();
    // Create multi-dim-dynamic array
    rows = vertices;
    cols = vertices;
    the_matrix = new T*[rows];
    for( int b = 0; b < rows; ++b)
    {
        the_matrix[b] = new T [rows];
    }
    // Initialize array values to zero
    for ( int c = 0; c < rows; ++c)
    {
       for( int d = 0; d < cols; ++d)
       {
           the_matrix[c][d] = 0;
       }
    }
    // push the edges to the matrix
    for( int e = 0; e < edges; ++e)
    {
        the_matrix[edge1[e] - 1][edge2[e] - 1] = 1;
    }
    for ( int f = 0; f < edges; ++f)
    {
        the_matrix[edge2[f] - 1][edge1[f]-1] = 1;
    }

}
// Copy Constructor
template <typename T>
matrix<T>::matrix(const matrix& left)
{
    the_matrix = left.the_matrix;
    rows = left.rows;
    cols = left.cols;
    spath = left.spath;
}
// Destructor
template <typename T>
matrix<T>::~matrix()
{ 
    // Deletes the data in reverse order of allocation
    for( int a = cols; a > 0; --a)
    {
        delete[ ] the_matrix[a];
    }
    delete[ ] the_matrix;
}
// Overloaded * Operator
template <typename T>
const matrix<T> matrix<T>::operator * (const matrix& right) const
{
    matrix<T> c = right;
    T sum_elems;
    for( int i = 0; i < this->rows - 1; ++i)
    {
        for(int j = 0; j < right.cols - 1; ++j)
        {
            sum_elems = 0;
            for( int k = 0; k < right.rows - 1; ++k)
            {
                sum_elems += this->the_matrix[i][k] * right.the_matrix[k][j];
            }
            c.the_matrix[i][j] = sum_elems;
        }
    }
    return c;
}
// Overloaded assignment Operator
template <typename T>
matrix<T>& matrix<T>::operator = (const matrix& right)
{
    this->the_matrix= right.the_matrix;
    this->rows = right.rows;
    this->cols = right.cols;
    this->spath = right.spath;
    return *this;
}
// Overloaded << operator
template <typename T>
std::ostream& operator << (std::ostream& output, const matrix<T>& left)
{
    // Test screen output to see if correct   
    std::cout << std::setw(14) << "The Matrix:" << 'n';
    for( int a = 0; a < left.rows; ++a)
    {
        for( int b = 0; b < left.cols; ++b)
        {
            std::cout << ' ' << left.the_matrix[a][b] << ' ';
        }
        std::cout << 'n';
    }
    return output;
}

正如我所怀疑的,您的复制构造函数和赋值运算符实际上没有正确实现。您只是在复制指针。这意味着,当您将一个矩阵复制到另一个矩阵时,它们共享相同的数据。当其中一个超出范围时,将调用析构函数,然后删除共享数据,剩下的矩阵带有悬空指针。

修复这些函数,使它们能够实际分配新的数组,并复制数据。

  1. i实际上从0变为this->rows - 2(因为i = n-1i < n-1为假)。其他回路也是如此。这似乎不是矩阵乘法的正确行为
  2. 尽管如此,这个代码片段似乎是正确的。你能为我们提供完整的类实现吗

附言:如果T是矩阵元素的类型,那么sum_elems的类型应该是T