I’m writing this question with reference to this one which I wrote yesterday. After a little documentation, it seems clear to me that what I wanted to do (and what I believed to be possible) is nearly impossible if not impossible at all. There are several ways to implement it, and since I’m not an experienced programmer, I ask you which choice would you take. I explain again my problem, but now I have some solutions to explore.
What I need
I have a Matrix class, and I want to implement multiplication between matrices so that the class usage is very intuitive:
Matrix a(5,2); a(4,1) = 6 ; a(3,1) = 9.4 ; ... // And so on ... Matrix b(2,9); b(0,2) = 3; ... // And so on ... // After a while Matrix i = a * b;
What I had yesterday
At the moment I overloaded the two operators operator* and operator= and until yesterday night the were defined in this way:
Matrix& operator*(Matrix& m); Matrix& operator=(Matrix& m);
The operator* instantiates a new Matrix object (Matrix return = new Matrix(...)) on the heap, set the values and then just:
return *result;
What I have today
After the discussion I decided to implement it in a ‘different way’ to avoid the user to be bothered bother by pointers of any type and to keep the usage unchanged. The ‘different way’ is to pass the returning value of operator* by value:
Matrix operator*(Matrix& m); Matrix& operator=(Matrix& m);
The operator* instantiates return on the stack, set the values and then return the object.
There is a problem with this approach: it doesn’t work. The operator= expects a Matrix& and operator* returns a Matrix. Moreover this approach doesn’t look so good to me for another reason: I’m dealing with matrices, that can be very large and the aims of this library were to be 1) good enough for my project 2) fast, so probably passing by value should not be an option.
Which solutions I have explored
Well, following the suggestions in the previous discussion I read some stuff about smart pointers, they look great but I can’t still figure out how to solve my problem with them. They deal with memory freeing and pointer copying, but I’m basicly using references, so they don’t look the right choice for me. But I may be wrong.
Maybe the only solution is to pass by value, maybe I can’t get both efficiency and a good interface. But again, you’re the expert, and I would like to know your opinion.
The problem you are having is that the expression
a * bcreates a temporary object, and in C++, a temporary is not allowed to bind to a non-constant reference, which is what yourMatrix& operator=(Matrix& m)takes. If you change it to:The code should now compile. As well as the obvious benefit of producing compilable code :), adding the
constalso communicates to your callers that you will not be modifying the argumentm, which may be helpful information.You should also do the same for your
operator*():[EDIT: The additional
constat the end indicates that the method promises not to alter*this, the object on the left-hand side of the multiplication, either. This is necessary to cope with expressions such asa * b * c— the subexpressiona * bcreates a temporary and won’t bind without theconstat the end. Thanks to Greg Rogers for pointing this out in the comments.]P.S. The reason why C++ does not allow a temporary to bind to a non-constant reference is because temporaries exist (as the name suggests) for only a very short time, and in most cases, it would be a mistake to attempt to modify them.