I have been using C++ for some time and there's still at least one thing I cannot manage to understand, nor I could find a good explanation surfing on the Web. It has something to do with memory managment and can be illustraded with this example:
Consider the string concatenation operator of std::string which looks like this
std::string operator+(const string& s1, string& s2)
which, as everybody knows, returns a newly created object (another std::string) containing the two original string concatenated. My question is: how is this possible? where does this object lies in memory?
I mean, if I had to write the function implementation I would do something like this
std::string std::string::operator+(const string& s1, string& s2)
{
std::string *res=new std::string;
// fill res with the content of s1 and s2
return *res;
}
but in this way I know I would cause a memory leak because if I called the function one million times I would generate one million strings which wouldn't be deallocated until the program's end. On the other hand I could do this:
std::string& std::string::operator+(const string& s1, string& s2)
{
std::string res;
// fill res with the content of s1 and s2
return res;
}
But in this way i would return a reference to a local variable which becomes garbage as soon as the function returns. Finally I could simply write
std::string std::string::operator+(const string& s1, string& s2)
{
std::string res;
// fill res with the content of s1 and s2
return res;
}
and pass the result by value, this should accomplish the mission but seems to me very inefficient because I have to copy the whole res (which in theory could be very large) object to the calling function. I say this because I'm actually working on a linear algebra library and it would be very nice to perform e.g. matrix addition with just
m3=m1+m2;
just as with string concatenation, but if the only solution is to copy back the resulting object, it is unpratical with a double matrix of, say, 100MB. At the moment the function I use is
matrix& matrix::sum(matrix& m1, matrix& m2)
which get used in this way
m3.sum(m2,m1);
which looks ugly and also prevents me from summing multiple matrix in a single line, I have to write
m4.sum(m1,m2)
m4.sum(m4,m3)
or
(m4.sum(m1,m2)).(m4,m3)
if I really want to make it in a single line but it is absolutely unreadable.
Is there a better way to do all this stuff?
Thanks in advance
This version is correct
std::string std::string::operator+(const string& s1, string& s2)
{
std::string res;
// fill res with the content of s1 and s2
return res;
}
Most compilers employ an optimization technique called named return value optimization to deal with the inefficiency of copying the value. It is expressly permitted by the standards, called copy elision.
In C++11 there is another way: when you return the string res
, it becomes an r-value, and move constructor will be used in place of copy constructor, and that is cheap as well. But again, most compilers optimize away both copy and move.
At last, I don't know why you have to implement a matrix library by yourself. If it is not a homework, use Eigen instead. Optimizing matrix algebra is very hard work that requires a lot of low level understanding.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With