Умножение матриц с перегрузкой операторов - PullRequest
3 голосов
/ 19 февраля 2012

Я пытаюсь создать перегруженный оператор для созданного мной матричного класса. Мой класс матрицы хранит матрицу в динамически распределенном многомерном массиве. Я просто пытаюсь проверить мой перегруженный оператор путем умножения двух одинаковых матриц и отображения вывода. Я получаю странные результаты, и я верю, что это связано с одним из условий на моих циклах for. Однако я прошел через все свои петли для и не могу найти ничего плохого. Матрицы, которые я умножаю вместе, имеют размер 6х6.

Мой перегруженный оператор

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;
}

Ответы [ 2 ]

6 голосов
/ 19 февраля 2012

Как я и подозревал, ваш конструктор копирования и оператор присваивания на самом деле не реализованы правильно.Вы просто копируете указатель.Это означает, что когда вы копируете одну матрицу в другую, они оба используют одни и те же данные.Когда один из них выходит из области видимости, вызывается деструктор, затем общие данные удаляются, оставляя оставшуюся матрицу с висячими указателями.

Исправьте эти функции, чтобы они фактически выделяли новые массивы, и копируйте данные.

1 голос
/ 19 февраля 2012
  1. i фактически переходит от 0 к this->rows - 2 (поскольку i < n-1 для i = n-1 ложно).То же самое для других петель.Кажется, что это неправильное поведение для умножения матриц.
  2. Тем не менее, этот фрагмент кода кажется правильным.Можете ли вы предоставить нам полную реализацию класса?

PS Если T - это тип матричных элементов, то тип sum_elems должен быть T.

...