C ++ string concatenation optimization

Looking at a piece of code like this (added comments):

std::string some_var;
std::string some_func(); // both are defined, but definition is irrelevant
...
return "some text " + some_var + "c" + some_func(); // intentionally "c" not 'c'

I was wondering in what cases operator +of std::stringshould make a copy (in the sense of using copy-construction / assign, and not for copying the internal buffer, for example, if SSO is used) and what is actually copied . A quick look at cppreference was only partially useful, as it lists 12 (!) Different cases. In part, I ask you to confirm your understanding of the page:

  • Case 1) makes a copy of lhs, and then copies rhs to the end of this copy.
  • In C ++ 98 Case 2) - 5) the time line is constructed from an argument char/const char*, which leads to case 1)
  • In C ++ 11 Case 2) - 5) the time line is constructed from char/const char*, which then leads to case 6) or 7)
  • In C ++ 11 Case 6) - 12) the r-value argument will be mutated with insert/append, and if the argument was provided char/const char*, temporary ones are not needed due to overloads on insert/append. In all cases, r is returned to facilitate further chaining. Copies are not copied (except for copies of arguments to be added / pasted at the insertion point). You may need to move the contents of the string.

Thus, a chain similar to the above example should lead to: 2) → 6) → 11) → 8), without any copies of any lhs, but simply changing the buffer of the r-value received from the first operation (creation time line).

, operator +=, operator + r-value. , operator += operator + ++ 11 , l-value?

?

: . ( ); .

+4
2

- : char , . , . , , .

:

... ( , / ). , .

, , ...

, , , . - as-if , , . ++ :

1.9 [intro.execution]
...
5 , , .

, :

, , , .

, a = a + b; a += b; .

++: , , . , , , , .

0

, ( , , ...), (, , str):

void concat (const std::list<std::string>& ls, std::string& str) {
  size_t ns (0);
  std::list<std::string>::const_iterator i (ls.begin());
  for (; i != ls.end (); i++) ns += i->size ();
  str.reserve (ns);
  str.erase (str.begin (), str.end ());
  for (i = ls.begin (); i != ls.end (); i++) str.append (*i);
}
-1

Source: https://habr.com/ru/post/1667792/


All Articles