Question: ```
std::string Concatenate(const std::string& s1,
                        const std::string& s2,
                        const std::string& s3,
                        const std::string& s4,
                        const std::string& s5)
{
    return s1 + s2 + s3 + s4 + s5;
}

```

By default, `return s1 + s2 + s3 + s4 + s5;` may be equivalent to the following code:

```
auto t1 = s1 + s2; // Allocation 1
auto t2 = t1 + s3; // Allocation 2
auto t3 = t2 + s4; // Allocation 3

return t3 + s5; // Allocation 4

```

Is there an elegant way to reduce the allocation times to 1? I mean keeping `return s1 + s2 + s3 + s4 + s5;` not changed, but the efficiency is improved automatically. If it is possible, it can also avoid the programmer misusing `std::string::operator +`.

Does **ref-qualifier** member functions help?

Answer: 
The premise of the question that:

```
s1 + s2 + s3 + s4 + s5 + ... + sn

```

will require n allocations is incorrect.

Instead it will require O(Log(n)) allocations. The first `s1 + s1` will generate a temporary. Subsequently a temporary (rvalue) will be the left argument to all subsequent `+` operations. The standard specifies that when the lhs of a `string +` is an rvalue, that the implementation simply append to that temporary and move it out:

```
operator+(basic_string<charT,traits,Allocator>&& lhs,
          const basic_string<charT,traits,Allocator>& rhs);

Returns: std::move(lhs.append(rhs))

```

The standard also specifies that the capacity of the string will grow geometrically (a factor between 1.5 and 2 is common). So on every allocation, capacity will grow geometrically, and that capacity is propagated down the chain of `+` operations. More specifically, the original code:

```
s = s1 + s2 + s3 + s4 + s5 + ... + sn;

```

is *actually* equivalent to:

```
s = s1 + s2;
s += s3;
s += s4;
s += s5;
// ...
s += sn;

```

When geometric capacity growth is combined with the short string optimization, the value of "pre-reserving" the correct capacity is limited. I would only bother doing that if such code actually shows up as a hot spot in your performance testing.
How about this:

```
std::string Concatenate(const std::string& s1,
                        const std::string& s2,
                        const std::string& s3,
                        const std::string& s4,
                        const std::string& s5)
{
    std::string ret;
    ret.reserve(s1.length() + s2.length() + s3.length() + s4.length() + s5.length());
    ret.append(s1.c_str());
    ret.append(s2.c_str());
    ret.append(s3.c_str());
    ret.append(s4.c_str());
    ret.append(s5.c_str());
    return ret;
}

```

There are two allocations, one really small to construct `std::string` another reserves memory for data.