【问题标题】:Matrix Multiplication with operator overloading带有运算符重载的矩阵乘法
【发布时间】:2012-03-09 23:30:27
【问题描述】:

我正在尝试为我构建的矩阵类创建一个重载运算符。我的矩阵类将矩阵存储在动态分配的多维数组中。我只是想通过将两个完全相同的矩阵相乘并显示输出来测试我的重载运算符。我得到了奇怪的结果,我相信这与我的 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;
}

【问题讨论】:

  • 您的矩阵类是否正确复制自身?在复制构造函数和赋值运算符中?您说您使用“动态分配的多维数组”。这是否意味着您正在使用newdelete 手动管理内存,而不是使用向量?如果有,为什么?
  • 复制构造函数和赋值运算符工作完美。我没有使用vector,特别是因为我想了解更多关于使用运算符newdelete 并手动管理内存而不是总是依赖vector 来完成幕后工作。

标签: c++ templates matrix operator-overloading


【解决方案1】:

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

修复这些函数,以便它们实际分配新数组并复制数据。

【讨论】:

  • 你是绝对正确的。我没有意识到我只是在复制指针。一旦我修复了复制和赋值运算符,我的 * 运算符就可以正常工作了。感谢您的帮助!
【解决方案2】:
  1. i 实际上是从 0this-&gt;rows - 2 (因为 i &lt; n-1 对于 i = n-1 是错误的)。其他循环也一样。这似乎不是矩阵乘法的正确行为。
  2. 不过,这段代码似乎是正确的。能否为我们提供完整的类实现?

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

【讨论】:

  • 我已按要求添加了完整的实现
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-07-29
  • 1970-01-01
相关资源
最近更新 更多