Матричные операторы класса + и * заканчиваются на segfault - PullRequest
0 голосов
/ 08 июня 2019

В основном я должен сделать реализацию класса Matrix. Я сделал большую часть этого, но я наткнулся на определенную проблему, и я действительно не знаю, что на самом деле не так.

Во-первых, это мой matrix.hpp заголовок:

 #include <iostream>
 #include <vector>

class Matrix {

  int columns;
  int rows;
  std::vector<std::vector<int>> vals;
  int matcheck (std::vector<std::vector<int>>);

public:
  Matrix (int, int, std::vector<std::vector<int>>);
  Matrix (int, int);
  ~Matrix();
  const Matrix operator + (const Matrix&) const;
  const Matrix operator * (const Matrix&) const;
  Matrix &operator = (const Matrix&);

  void inverse (Matrix&);
  void setValues (Matrix&, std::vector<std::vector<int>>); 
  void printMatrix ();

  static void changeSize (Matrix&, int, int);
  static void transpose (Matrix&);
};

Далее реализации перегрузки оператора:

const Matrix Matrix::operator + (const Matrix& mat) const {

    if ( !(rows == mat.rows && columns == mat.columns) ) {

        std::cout << "For addition the matrices must be the same size.\n"; 
        exit(-1); 
    }

    Matrix res (mat.rows, mat.columns);

    for (unsigned int row = 0; row < rows; ++row) {

        for (unsigned int col = 0; col < columns; ++col) {

            res.vals[row][col] += this->vals[row][col] + mat.vals[row][col];
        }
    }

    return res;
}

const Matrix Matrix::operator * (const Matrix& mat) const {

    Matrix res (rows, mat.columns);

    if (columns != mat.rows) { 

        std::cout<<"For multiplication the matrix A's columns must be the same number as matrix B's rows\n"; 
        exit(-1);
    }

    for (unsigned int row = 0; row < rows; ++row) {

        for (unsigned int col = 0; col < mat.columns; ++col) {

            int sum = 0;

            for (unsigned int k = 0; k < columns; ++k) {

                sum = sum + (vals[row][k] * mat.vals[k][col]);
            }

            res.vals[row][col] = sum;
        }
    }

    return res;
}

Matrix &Matrix::operator = (const Matrix& mat) {

    rows = mat.rows;
    columns = mat.columns;
    vals = mat.vals;

    return *this;
}

Теперь, чтобы проиллюстрировать данный случай, в main() я сделал пару тестов, и это выглядит так:

 #include <iostream>
 #include "matrix.hpp"

int main() {

    Matrix mat(4, 4, { {1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1} });
    Matrix mat2(4, 4, { {2, 2, 2, 2}, {2, 2, 2, 2}, {2, 2, 2, 2}, {2, 2, 2, 2} });
    Matrix mat5(4, 2, { {1, 12}, {5, 66}, {9, 6}, {7, 19}});

    Matrix mat3 = mat + mat2;
    mat3.printMatrix();

    Matrix mat4 = mat * mat5;
    mat4.printMatrix();

    mat4 = mat2;
    mat4.printMatrix();

    Matrix MAT(4, 4);
    MAT.printMatrix();
    MAT = mat5;

    mat5.printMatrix();
    Matrix::transpose(mat5);
    mat5.printMatrix();

    mat5 = mat;
    mat5.printMatrix();
    mat5 = mat4 + mat2;

    return 0;
}

Теперь все операции, предшествующие последней, работают довольно хорошо. Но как только я доберусь до последнего (mat5 = mat4 + mat2), я получу ошибку сегмента. Кроме того, если я использую * вместо этого, я получаю еще segfault. То же самое происходит, если я пытаюсь создать экземпляр объекта Matrix или если я использую любую из своих функций, например transpose().

Я изменил свои реализации операторов, а также немного погуглил, они, кажется, в порядке, или, по крайней мере, мне кажется.

Возможно, я просто тупой, но я действительно не могу этого понять. Заранее спасибо.

EDIT:

Функция transpose():

void Matrix::transpose (Matrix& mat) {

    Matrix res (mat.rows, mat.columns);
    res = mat;
    changeSize (mat, mat.columns, mat.rows);

    for (unsigned int col = 0; col < res.rows; ++col) {

        for (unsigned int row = 0; row < res.columns; ++row) {

            mat.vals[row][col] = res.vals[col][row];
        }
    }
}

И changeSize(), а также:

void Matrix::changeSize (Matrix& mat, int rows, int cols) {

    mat.vals.clear();

    mat.rows = rows;
    mat.columns = cols; 
}

EDIT:

Я также делюсь всем исходным файлом matrix.cpp, чтобы я мог предоставить полностью воспроизводимую программу. Я вставил ссылку для вставки, так как у меня уже достаточно кода, а вставка всего исходного файла сделает публикацию огромной. https://pastebin.com/AmJqhjKT

1 Ответ

1 голос
/ 09 июня 2019

changeSize обновляет элементы rows и columns, но оставляет вектор пустым. Любая ссылка на него впоследствии будет неопределенным поведением.

changeSize и transpose могут / должны быть нестатическими функциями-членами, поскольку вы передаете матрицу в качестве первого параметра и возвращаете результат в том же объекте.

...