I'm trying to write a C++ Class for managing data in a specific way. More Specific: to mimic mathmatical Matrix behavior like matrix-multiplication and stuff like that with as little overhead as possible. Intuitively i would like to use overloaded operators for better readability, but i always wonder about the additional allocation for returning the result-Matrix. Especially regarding performance if you think about a really large Matrix.
So far, i got everything set up to allocate and correctly access the stored Data by providing dimension coordinates. The objects are Heap allocated as Pointers to do some fancy stuff with transforming the Matrix. Adding looks like this so far:
Matrix* Add(Matrix* A, Matrix* B, Matrix* result)
{
[...] //Math here
return result;
}
So when calculating, the result is directly written into the result object since its acessed via Pointer.
But when using operator overloading, my confusion starts to grow. I would implement something like this (simplified, minimal problem):
Matrix* operator+(Matrix& other)
{
Matrix* result = new Matrix;
[...] //Math here
return result;
}
Imagine we live in a perfect world and leackage is magically solved, there is still the problem, that i dont see a way around allocating memory for the result internally. If i already have the object preallocated or i recycle one from previous calculations, isn't allocating the result memory waste of computational power? Is there a more efficient way around this or is maybe somehow internally optimized in a way i dont know of?
To a large extent, the problem you are worried about has been solved already. Consider this dummy matrix and example of calling operator+
:
#include <iostream>
struct matrix {
matrix() = default;
matrix(const matrix&) { std::cout << "copy!!!\n";}
matrix operator+(matrix& other) {
matrix result;
return result;
}
};
int main() {
std::cout << "how many copies?\n";
matrix a,b;
matrix c = a + b;
};
I left out the actual matrix elements and the addition, so we can focus on return result;
. You are worried about the copy that is made. Due to copy elision the output of the code is:
how many copies?
No copy is made. Copy elision underwent some substantial changes (from non-mandatory to mandatory in some cases), and for details I refer you to What are copy elision and return value optimization? and https://en.cppreference.com/w/cpp/language/copy_elision.
However, to get good efficiency also with more complex expressions, eg matrix a = (a + b) * c + (d + e) * f;
, you should consider expression templates (eg https://en.wikipedia.org/wiki/Expression_templates). It's a technique to defer actual computation until the result is actually needed (eg in the example no temporary as result of a+b
is required mathematically, but by C++, though C++ allows to return arbitrary custom type from operator+
, it needs not be readily computed matrix).