0

I am trying a program to perform basic matrix operation using operator overloading. below is my code :-

class for holding matrix

class matrix {
    int r, c;
    int *data;

    public :
    matrix()  //default contstructor
    {
        r=0; c=0;
        data = NULL;
    }

    matrix(int a, int b)   //general matrix constructor.
    {
        r = a; c = b;
        data = new int[sizeof(int) * r * c];;
    }

    //Overloading + operator.
    matrix operator +(matrix & M);

             //Overloading = operator.
    void operator =(matrix & M);
};

then I have created a temporary global object as below.

matrix temp;

I have overloaded + operator as below. Note that I have to use the global object 'temp' created above to save and return resultant matrix as one on my data member is int* and I cannot return objects with local scope.

// Addition of matrix
matrix matrix :: operator+(matrix & M)
{
         if(M.r != r || M.c != c) {
           cout<<"Addition is not possible!";
           return temp;
         }
         temp.r = r;
         temp.c = c;
         temp.data = new int(sizeof(int) * r * c);

         for(int i=0; i<r; i++)
         for(int j=0; j<c; j++)
          *(temp.data +(i*c +j)) = *(data +(i*c +j)) + *(M.data +(i*c +j));

     return temp;
}

ok, the program works well... but my question is is there any efficient alternative to this external "temp" object?

5
  • The temp copy is extremely likely to be elided, so the only inefficiencies you should worry about is when you have expressions such as m0 + m1 + m2 + m2 where the mi are all matrices. A common solution to this is expression templates, but it is tricky. Commented Oct 30, 2013 at 10:52
  • Aside: your operators should be const, and act on const references: matrix operator +(const matrix & M) const;, and the size of your arrays looks suspicious. Commented Oct 30, 2013 at 10:53
  • 2
    Why would you declare the temporary object as a global? Just declare it as a local variable inside the function. Commented Oct 30, 2013 at 10:54
  • What @JoachimPileborg said. What I said about copy elision assumes temp is a local variable in the operator. Commented Oct 30, 2013 at 10:55
  • 1
    It's quite common to make the row and column parameters template arguments. E.g. Matrix<4, 4>. This makes it a compile-time error to add a Matrix<4,4> to a Matrix<3,3>. Commented Oct 30, 2013 at 11:03

1 Answer 1

2

is there any efficient alternative to this external "temp" object?

Yes (and also, there are some problems in the code).

The matrix sum should be implemented in two ways:

class matrix {
    // ...

    //Overloading + operator.
    matrix& operator +=(const matrix& M); // << notice difference in signature
};

// Addition of matrix
matrix& matrix::operator +=(const matrix& M)
{
     if(M.r != r || M.c != c) {
         cout<<"Addition is not possible!"; // this should throw an exception
                                            // because client code should not have to
                                            // be forced to check the contents of
                                            // std::cout to validate that the operation
                                            // succeeded

         return *this;                      // returning *this
     }

     // this is not necessary
     // temp.r = r;
     // temp.c = c;
     // temp.data = new int(sizeof(int) * r * c);

     for(int i=0; i<r; i++)
         for(int j=0; j<c; j++)
             *(data +(i*c +j)) = *(data +(i*c +j)) + *(M.data +(i*c +j));

     return *this;                          // returning *this
}

This is the concatenation (+=) operator and it's efficient because it doesn't create new/temporary objects. The problem it has is that it alters the left-hand operand.

Second implementation (as efficient as your first, and completing the code above):

matrix operator +(const matrix& x, const matrix& y) {
    matrix result(x); // you will need a copy constructor
    result += y;      // use operator defined above
    return result;
}

The second implementation uses the first to add addition semantics for matrix and it doesn't need to be a member.

Sign up to request clarification or add additional context in comments.

2 Comments

Note that if you have written operator+= you don't have to write operator+ yourself, use Boost.Operators or my df.operators library, the second allowing to optimize away some temporaries in expressions like auto result = m1 + m2 + m3 + m4;.
I know, but the OP is working on the correct signature and semantics of defining an addition operator. Adding 3rd party libraries, optimizations allowed by C++11 and/or inheritance, templates and CRTP to the example is a bit premature. I could have added a lot more improvements and advice to the code (e.g. use std::vector) but I wanted to focus on getting the function signature and (very basic) implementation correct.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.