c++ operator overloading

I am writing a class for a matrix with such functions:

  • inverse(A^-1)
  • sum(+)
  • difference(-)
  • product(*)

When I run the program, it outputs incorrect values and an error double free or corruption (out). help me find out what the problem is. when entering a 2x2 matrix, it outputs only one correct value for (+, -). and when entering a 3x3 matrix, it outputs 4 correct values out of 9.

#include <iostream>
using namespace std;


class matrix
{
  int Row, Col;  //строки и столбцы
  double **Value;  // элементы матрицы
  public:

  matrix(int, int);  //конструктор
  matrix(matrix&); //копирующий конструктор - создает копию объекта m
  int GetRow(); //метод получает значение числа строк
  int GetCol(); //метод получает значение числа столбцов
  double& operator()(int, int); //перегрузка скобок для матрицы

  friend istream& operator>>(istream &istr, matrix &m);//перегрузка оператора ввода
  friend ostream& operator<<(ostream &ostr, matrix &m);//перегрузка оператора вывода
  friend matrix operator+(matrix &m1, matrix &m2);//перегрузка оператора плюс (бинарный)
  friend matrix operator-(matrix &m1, matrix &m2);//перегрузка оператора минус (бинарный)

  ~matrix(); //деструктор
};

  matrix::matrix(int row,int col)
  {
    Row=row;  //переменным Row и Col присваиются вводимые значения числа строк и столбцов матрицы
    Col=col;
    Value=new double*[row];  //конструктор создает двумерный динамический массив
    for (int i=0; i<row; i++) Value[i]=new double[col];
  }

  matrix::matrix(matrix& m) //копирующий конструктор - создает копию матрицы m
  {
    Value=new double *[Row];
    for (int i=0; i<Row; i++)  Value[i]=new double[Col];
    for (int i=0; i<Row; i++)
      {
      for (int j=0; j<Col; j++)
         Value[i][j] = m(i,j);
      } // значения элементов матрицы будут такими же, как у матрицы m
    }

  int matrix::GetRow() //функция получает значение числа строк
  {
    return (Row);
  }

  int matrix::GetCol() //функция получает значение числа столбцов
  {
    return (Col);
  }

  istream &operator>>(istream &istr, matrix &m) // перегрузка оператора ввода матрицы
  {
    for (int i=0; i<m.GetRow(); i++)
      for (int j=0; j<m.GetCol(); j++)
        istr>>m(i, j);
    return(istr);
  }

  ostream &operator<<(ostream &ostr, matrix &m) //перегрузка оператора вывода матрицы
  {
    for (int i=0; i<m.GetRow(); i++)
    {
      for (int j=0; j<m.GetCol(); j++)
        ostr<<m(i,j)<<"\t";
      ostr<<"\n";
    }
    return(ostr);
  }

  matrix operator+(matrix &m1, matrix &m2) //перегрузка оператора плюс (бинарный)
  {
    matrix temp(m1.GetRow(),m1.GetCol());
    for (int i = 0; i<m1.GetRow(); i++)
      for (int j = 0; j<m1.GetCol(); j++)
        temp(i,j)=m1(i,j)+m2(i,j);
    return(temp);
  }

  matrix operator-(matrix &m1, matrix &m2) //перегрузка оператора минус (бинарный)
  {
    matrix temp1(m1.GetRow(),m1.GetCol());
    for (int i = 0; i<m1.GetRow(); i++)
      for (int j = 0; j<m1.GetCol(); j++)
        temp1(i,j)=m1(i,j)-m2(i,j);
    return(temp1);
  }

  double& matrix::operator()(int row, int col)//перегрузка круглых скобок для матрицы.
  {                             // Если m - матрица, то m(i,j) будет
    return (Value[row][col]);  //означать i,j-тый элемент матрицы
  }

  matrix::~matrix() //деструктор
  {
    for (int i=0; i<Row; i++)
      delete[] Value[i]; //деструктор удаляет из памяти динамический массив, созданный конструктором
    delete[] Value;
  }

int main()
{
  int m,n;
  cout<<"enter number of rows and columns of matrices: "; cin>>m>>n;
  matrix a(m,n);
  matrix b(m,n);
  matrix c(m,n);
  cout<<"enter matrix A:\n";  cin>>a;
  cout<<"enter matrix B:\n";  cin>>b;
  c=a+b;
  cout<<"sum of two matrices A and B :\n"<<c;    
  c=a-b;
  cout<<"subtraction of two matrices A and B :\n"<<c;
  return 0;
}

Here's how it works program

$ ./a.out 
enter number of rows and columns of matrices: 2 2
enter matrix A:
4 5
6 3
enter matrix B:
8 9
7 1
sum of two matrices A and B :
0   1.63042e-322    
8.66416e-317    4   
subtraction of two matrices A and B :
0   1.63042e-322    
8.66417e-317    2   
*** Error in `./a.out': double free or corruption (out): 0x00000000010b95c0 ***
======= Backtrace: =========
/lib/x86_64-linux-gnu/libc.so.6(+0x777e5)[0x7fc213dec7e5]
/lib/x86_64-linux-gnu/libc.so.6(+0x8037a)[0x7fc213df537a]
/lib/x86_64-linux-gnu/libc.so.6(cfree+0x4c)[0x7fc213df953c]
./a.out[0x40107b]
./a.out[0x401220]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf0)[0x7fc213d95830]
./a.out[0x4009c9]
======= Memory map: ========
00400000-00402000 r-xp 00000000 00:2e 1178660                            /home/neo/Desktop/class matrix/a.out
00601000-00602000 r--p 00001000 00:2e 1178660                            /home/neo/Desktop/class matrix/a.out
00602000-00603000 rw-p 00002000 00:2e 1178660                            /home/neo/Desktop/class matrix/a.out
010a7000-010d9000 rw-p 00000000 00:00 0                                  [heap]
7fc20c000000-7fc20c021000 rw-p 00000000 00:00 0 
7fc20c021000-7fc210000000 ---p 00000000 00:00 0 
7fc213a6c000-7fc213b74000 r-xp 00000000 08:04 267638                     /lib/x86_64-linux-gnu/libm-2.23.so
7fc213b74000-7fc213d73000 ---p 00108000 08:04 267638                     /lib/x86_64-linux-gnu/libm-2.23.so
7fc213d73000-7fc213d74000 r--p 00107000 08:04 267638                     /lib/x86_64-linux-gnu/libm-2.23.so
7fc213d74000-7fc213d75000 rw-p 00108000 08:04 267638                     /lib/x86_64-linux-gnu/libm-2.23.so
7fc213d75000-7fc213f35000 r-xp 00000000 08:04 267650                     /lib/x86_64-linux-gnu/libc-2.23.so
7fc213f35000-7fc214135000 ---p 001c0000 08:04 267650                     /lib/x86_64-linux-gnu/libc-2.23.so
7fc214135000-7fc214139000 r--p 001c0000 08:04 267650                     /lib/x86_64-linux-gnu/libc-2.23.so
7fc214139000-7fc21413b000 rw-p 001c4000 08:04 267650                     /lib/x86_64-linux-gnu/libc-2.23.so
7fc21413b000-7fc21413f000 rw-p 00000000 00:00 0 
7fc21413f000-7fc214155000 r-xp 00000000 08:04 267576                     /lib/x86_64-linux-gnu/libgcc_s.so.1
7fc214155000-7fc214354000 ---p 00016000 08:04 267576                     /lib/x86_64-linux-gnu/libgcc_s.so.1
7fc214354000-7fc214355000 rw-p 00015000 08:04 267576                     /lib/x86_64-linux-gnu/libgcc_s.so.1
7fc214355000-7fc2144c7000 r-xp 00000000 08:04 1509                       /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.21
7fc2144c7000-7fc2146c7000 ---p 00172000 08:04 1509                       /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.21
7fc2146c7000-7fc2146d1000 r--p 00172000 08:04 1509                       /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.21
7fc2146d1000-7fc2146d3000 rw-p 0017c000 08:04 1509                       /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.21
7fc2146d3000-7fc2146d7000 rw-p 00000000 00:00 0 
7fc2146d7000-7fc2146fd000 r-xp 00000000 08:04 267512                     /lib/x86_64-linux-gnu/ld-2.23.so
7fc2148c8000-7fc2148cd000 rw-p 00000000 00:00 0 
7fc2148f9000-7fc2148fc000 rw-p 00000000 00:00 0 
7fc2148fc000-7fc2148fd000 r--p 00025000 08:04 267512                     /lib/x86_64-linux-gnu/ld-2.23.so
7fc2148fd000-7fc2148fe000 rw-p 00026000 08:04 267512                     /lib/x86_64-linux-gnu/ld-2.23.so
7fc2148fe000-7fc2148ff000 rw-p 00000000 00:00 0 
7ffdf38fc000-7ffdf391d000 rw-p 00000000 00:00 0                          [stack]
7ffdf39b3000-7ffdf39b5000 r--p 00000000 00:00 0                          [vvar]
7ffdf39b5000-7ffdf39b7000 r-xp 00000000 00:00 0                          [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0                  [vsyscall]
Aborted

Update after this answer

After the fix, everything worked (+, -, and*). I also wanted to find the inverse matrix(for A and B).

matrix matrix::inverse(matrix &m)   //метод нахождения обратной матрицы
{
  double t;
  int n=m.GetRow();
  for(int i=0;i<n;i++)
  {
    for(int j=n;j<2*n;j++)
    {
      if(i==j-n)
        m(i,j)=1;
      else
        m(i,j)=0;
    }
  }
  for(int i=0;i<n;i++)
  {
    t=m(i,i);
    for(int j=i;j<2*n;j++)
      m(i,j)/=t;
    for(int j=0;j<n;j++)
    {
      if(i!=j)
      {
        t=m(j,i);
        for(int k=0;k<2*n;k++)
          m(j,k)-=t*m(i,k);
      }
    }
}
return (m);
}

...

c=a.inverse(a);

But it outputs this:

...
inverse of matrix A:
1   0   
0   1   
Segmentation fault
Author: mend4x, 2017-12-02

1 answers

To begin with: what do you have in the first lines equal to Row and Col:

matrix::matrix(matrix& m) //копирующий конструктор - создает копию матрицы m
{
    Value=new double *[Row];
    for (int i=0; i<Row; i++)  Value[i]=new double[Col];

? (by the way, it is better to pass the constant reference to the copying constructor).

And there is no assignment operator at all - and the generated one by default will perform a surface copy of pointers, and not what they point to - with all the consequences such as double deletion, etc...

Update

Sorry, there is no time for long explanations - figure it out for yourself, how the corrected code works:

#include <iostream>
using namespace std;


class matrix
{
    int Row, Col;  //строки и столбцы
    double **Value;  // элементы матрицы
public:

    matrix(int, int);  //конструктор
    matrix(const matrix&); //копирующий конструктор - создает копию объекта m
    int GetRow(); //метод получает значение числа строк
    int GetCol(); //метод получает значение числа столбцов
    double& operator()(int, int); //перегрузка скобок для матрицы
    double operator()(int, int) const; //перегрузка скобок для матрицы

    friend istream& operator>>(istream &istr, matrix &m);//перегрузка оператора ввода
    friend ostream& operator<<(ostream &ostr, matrix &m);//перегрузка оператора вывода
    friend matrix operator+(matrix &m1, matrix &m2);//перегрузка оператора плюс (бинарный)
    friend matrix operator-(matrix &m1, matrix &m2);//перегрузка оператора минус (бинарный)

    ~matrix(); //деструктор

    matrix& operator=(const matrix& m)
    {
        matrix tmp(m);
        swap(tmp);
        return *this;
    }

private:
    void swap(matrix&m)
    {
        {
            int tmp = Row; Row = m.Row; m.Row = tmp;
            tmp = Col; Col = m.Col; m.Col = tmp;
        }
        double ** tmp = Value; Value = m.Value; m.Value = tmp;
    }

};

matrix::matrix(int row,int col)
{
    Row=row;  //переменным Row и Col присваиются вводимые значения числа строк и столбцов матрицы
    Col=col;
    Value=new double*[row];  //конструктор создает двумерный динамический массив
    for (int i=0; i<row; i++) Value[i]=new double[col];
}

matrix::matrix(const matrix& m) //копирующий конструктор - создает копию матрицы m
:Row(m.Row),Col(m.Col)
{
    Value=new double *[Row];
    for (int i=0; i<Row; i++)  Value[i]=new double[Col];
    for (int i=0; i<Row; i++)
    {
        for (int j=0; j<Col; j++)
            Value[i][j] = m.Value[i][j];
    } // значения элементов матрицы будут такими же, как у матрицы m
}

int matrix::GetRow() //функция получает значение числа строк
{
    return (Row);
}

int matrix::GetCol() //функция получает значение числа столбцов
{
    return (Col);
}

istream &operator>>(istream &istr, matrix &m) // перегрузка оператора ввода матрицы
{
    for (int i=0; i<m.GetRow(); i++)
        for (int j=0; j<m.GetCol(); j++)
            istr>>m(i, j);
    return(istr);
}

ostream &operator<<(ostream &ostr, matrix &m) //перегрузка оператора вывода матрицы
{
    for (int i=0; i<m.GetRow(); i++)
    {
        for (int j=0; j<m.GetCol(); j++)
            ostr<<m(i,j)<<"\t";
        ostr<<"\n";
    }
    return(ostr);
}

matrix operator+(matrix &m1, matrix &m2) //перегрузка оператора плюс (бинарный)
{
    matrix temp(m1.GetRow(),m1.GetCol());
    for (int i = 0; i<m1.GetRow(); i++)
        for (int j = 0; j<m1.GetCol(); j++)
            temp(i,j)=m1(i,j)+m2(i,j);
    return(temp);
}

matrix operator-(matrix &m1, matrix &m2) //перегрузка оператора минус (бинарный)
{
    matrix temp1(m1.GetRow(),m1.GetCol());
    for (int i = 0; i<m1.GetRow(); i++)
        for (int j = 0; j<m1.GetCol(); j++)
            temp1(i,j)=m1(i,j)-m2(i,j);
    return(temp1);
}

double& matrix::operator()(int row, int col)//перегрузка круглых скобок для матрицы.
{                             // Если m - матрица, то m(i,j) будет
    return (Value[row][col]);  //означать i,j-тый элемент матрицы
}

double matrix::operator()(int row, int col) const//перегрузка круглых скобок для матрицы.
{                             // Если m - матрица, то m(i,j) будет
    return (Value[row][col]);  //означать i,j-тый элемент матрицы
}

matrix::~matrix() //деструктор
{
    for (int i=0; i<Row; i++)
        delete[] Value[i]; //деструктор удаляет из памяти динамический массив, созданный конструктором
    delete[] Value;
}

int main()
{
    int m,n;
    cout<<"enter number of rows and columns of matrices: "; cin>>m>>n;
    matrix a(m,n);
    matrix b(m,n);
    matrix c(m,n);
    cout<<"enter matrix A:\n";  cin>>a;
    cout<<"enter matrix B:\n";  cin>>b;
    c=a+b;
    cout<<"sum of two matrices A and B :\n"<<c << endl;
    c=a-b;
    cout<<"subtraction of two matrices A and B :\n"<<c << endl;
    return 0;
}
 1
Author: Harry, 2017-12-02 11:27:48