Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

String concatenation and memory managment

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

like image 252
woggioni Avatar asked Sep 18 '25 13:09

woggioni


1 Answers

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.

like image 105
Siyuan Ren Avatar answered Sep 21 '25 04:09

Siyuan Ren