-1

The following code gives me the wrong output. actually, it is not doing sum, it actually copies the 2nd object to the M3 object instead of calculating the sum. I think I have some logical errors in + operator overloading. Does anybody have any idea or any other suggestion? it displays the output actually which is called in the copy constructor function cout<data[r][c]<<"\t";. but it did not display output when I use M3.displayData(). #include

#include <string.h>
using namespace std;

class Matrix{
    private:
        int noOfRows;
        int noOfColumns;
        int **data;
    public:
        Matrix(int noOfRows, int noOfColumns);
        void displayData();
        ~Matrix();
        Matrix (const Matrix &ref);
        Matrix operator + (Matrix m);
        Matrix& operator=(Matrix m) { 
        std::swap(m.noOfRows, noOfRows); 
        std::swap(m.noOfColumns, noOfColumns); 
        std::swap(m.data, data); 
        return *this; }
};

Matrix::Matrix(int inr=0, int inc=0){
    noOfRows=inr; noOfColumns=inc;
    data=new int*[noOfColumns];
    for(int i=0;i<noOfRows;i++)
        data[i]=new int[noOfColumns];
    int d;
    for(int r=0;r<noOfRows;r++){
        for(int c=0;c<noOfColumns;c++){
            cout<<"Enter ...";cin>>d;
            data[r][c]=d;
        }
        cout<<endl;
    }
}

Matrix::Matrix (const Matrix &ref){
    this->data=new int*[ref.noOfColumns];
    for(int i=0;i<ref.noOfRows;i++)
        this->data[i]=new int[ref.noOfRows];
    
    for(int r=0;r<ref.noOfRows;r++){
        for(int c=0;c<ref.noOfColumns;c++){
            this->data[r][c]=ref.data[r][c];
            cout<<this->data[r][c]<<"\t";
        }
        cout<<endl;
    }
}

Matrix Matrix::operator + (Matrix m){
    Matrix ms(m.noOfRows,m.noOfColumns);
    ms=0;
    for (int i=0; i<m.noOfRows; i++) 
        for (int j=0; j<m.noOfColumns; j++){
        ms.data[i][j] = data[i][j]+m.data[i][j];
        return ms;
        } 
    }

void Matrix::displayData(){
    for(int r=0;r<noOfRows;r++){
        for(int c=0;c<noOfColumns;c++)
            cout<<data[r][c]<<"\t";
        cout<<endl;
    }
}

Matrix::~Matrix(){
    delete[] data;
}

int main(){
    Matrix M1(2,2),M2(2,2);
    cout<<"\n Matrix A="<<endl;
    M1.displayData();
    cout<<"\n Matrix B="<<endl;
    M2.displayData();
    cout<<"\n Sum of Matrix="<<endl;
    Matrix M3=M1+M2;
    M3.displayData();
    return 0;
}

Program output is here:

  • You return the matrix inside the loop, instead of at the end of the function. – ChrisMM Mar 29 '22 at 01:23
  • Your copy constructor does not initialize the matrix sizes. Because you're passing `Matrix` into your operators by value (instead of the correct way which is to pass by reference), this results in undefined behavior. Your allocations are also broken. Carefully check what dimensions you are allocating. Use your debugger. – paddy Mar 29 '22 at 01:23
  • You need a working, non-buggy copy constructor before implementing the assignment operator using `std::swap`. That's the prerequisitie. – PaulMcKenzie Mar 29 '22 at 01:28
  • Why are you using `std::swap` to assign values when implementing the assignment operator? – pale_rider Mar 29 '22 at 01:28
  • 2
    @pale_rider -- It is perfectly valid to use `std::swap`. There is nothing wrong with the assignment operator. This is the [copy/swap idiom](https://stackoverflow.com/questions/3279543/what-is-the-copy-and-swap-idiom). The issue is that the copy constructor is broken, and a working copy constructor is a requirement for the copy/swap to work. – PaulMcKenzie Mar 29 '22 at 01:30
  • Also broken is the `~Matrix()`, as it leaks memory. – PaulMcKenzie Mar 29 '22 at 02:15
  • SO what will be the possible solution??? – BS e-Learning Mar 29 '22 at 03:35

1 Answers1

0

There are at least four issues with your code:

  1. The Matrix copy constructor fails to copy the noOfRows and noOfColumns values.

  2. You erroneously allocated the row pointers by using noOfColumns as the number of rows.

  3. In the Matrix operator +, you are returning the Matrix inside the for loop, when you should be returning it after the loop is completed.

  4. Your destructor fails to delete[] all the row and column data.

To fix the first two issues, since there is a lot of common code between the Matrix default constructor and the copy constructor, you could create an Allocate member function to allocate the memory:

class Matrix
{
    private:
       void Allocate();
    //... other members
    public:
        Matrix operator + (const Matrix& m);
    // other members...
};

Matrix::Matrix(int inr=0, int inc=0) : noOfRows(inr), noOfColumns(inc)
{
    Allocate();
    // Input code removed...
}

Matrix::Matrix (const Matrix &ref) : noOfRows(ref.noOfRows), noOfColumns(ref.noOfColumns)
{
    Allocate();
    for(int r=0; r < ref.noOfRows; r++)
    {
        for(int c=0; c < ref.noOfColumns; c++)
            data[r][c] = ref.data[r][c];
    }
}

void Matrix::Allocate()
{
    data=new int*[noOfRows];
    for(int i=0;i < noOfRows; i++)
        data[i]=new int[noOfColumns]();
}

For operator +, you should pass the Matrix by const reference, not by value (this is in addition to fixing the mistake of returning the Matrix prematurely):

Matrix Matrix::operator + (const Matrix& m)
{
    Matrix ms(m.noOfRows,m.noOfColumns);
    for (int i=0; i<m.noOfRows; i++) 
    { 
        for (int j=0; j<m.noOfColumns; j++)
            ms.data[i][j] = data[i][j]+m.data[i][j];
    }
    return ms;
}

The last issue (the destructor) only removes the row pointers, but does not remove the data allocated for each row. The fix is below:

Matrix::~Matrix()
{
    for (int i = 0; i < noOfRows; ++i)
        delete[] data[i];
    delete [] data;
}

Other issues:

  1. Put more space between operators. Your current code squishes everything together, making it hard to read. For example:

for(int c=0;c<ref.noOfColumns;c++) could be: for (int c=0; c < ref.noOfColumns; c++)

  1. Excessive and unnecessary usage of this->.

  2. If Matrix::operator + exists, it makes sense for Matrix::operator += to also exist. For the latter, operator + would simply be implemented in terms of operator +=, making operator + one or two lines of code.

  3. A probably better method of allocating the memory is illustrated by this answer, since only two allocations are done, the memory allocated is contiguous, and less memory fragmentation will occur.

PaulMcKenzie
  • 34,698
  • 4
  • 24
  • 45
  • you have removed the input statements so where do I put these statements??? either in a new function?? or any other option in your point of view. – BS e-Learning Mar 29 '22 at 15:34
  • I removed them because they were not important in showing what the real issue is. Just put them back. And in all honesty, a `Matrix` class shouldn't have input placed in the middle of it. What if the input should come from a file or some other means? I/O should be outside the class, and instead, your `Matrix` class should have functions that allow the setting of the data, regardless of where the data comes from. – PaulMcKenzie Mar 29 '22 at 15:35
  • if I put this code in the constructor, it again asks for input data when we create an M3 object and again asks when we call M3=M1+M2, whereas the end result is showing perfectly. I think I must remove this input from the constructor and should put it in a separate function. – BS e-Learning Mar 29 '22 at 15:48
  • There should be *no* input in any of the `Matrix` class code. You should have additional member functions that set the `Matrix` values. What if I want to change the value in one of the `Matrix` entries? Is there a way to do that? No. – PaulMcKenzie Mar 29 '22 at 15:56
  • I have done this through spearating setData() function. when i use setData for M3, it dispaly addition perfectly, but if i did not input data in M3 object using setData function, it displays invalide output after addition. – BS e-Learning Mar 29 '22 at 18:56
  • `void Matrix::setData(){ for(int r=0;r>data[r][c]; } cout< – BS e-Learning Mar 29 '22 at 18:58
  • how to write code here in comments box??? – BS e-Learning Mar 29 '22 at 18:58
  • ```int main(){ Matrix M3(2,2);M3=0; Matrix M1(2,2);M1=1; Matrix M2(2,2);M2=2; //M1.setData();M2.setData();M3.setData(); cout<<"\n Matrix A = "< – BS e-Learning Mar 29 '22 at 19:04